353 Commits

Author SHA1 Message Date
3c62ff6913 chore(release): 6.10.1 [skip ci]
## [6.10.1](https://git.datacontroller.io/dc/dc/compare/v6.10.0...v6.10.1) (2024-06-07)

### Bug Fixes

* adding 60 more colours to crayons table. Closes [#112](#112) ([3521579](3521579dea))
* terms and conditions colours, editor on smaller screens show only icons ([e32d44b](e32d44b1bc))
2024-06-07 15:46:58 +00:00
f4f589af94 Merge pull request 'fix: adding 60 more colours to crayons table. Closes #112' (#114) from issue112 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m41s
Release / Build-and-test-development (push) Successful in 8m42s
Release / release (push) Successful in 10m11s
Reviewed-on: #114
2024-06-07 15:29:09 +00:00
3521579dea fix: adding 60 more colours to crayons table. Closes #112
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m45s
2024-06-07 16:23:40 +01:00
e97a6f52da Merge pull request 'fix: terms and conditions colours, editor on smaller screens show only icons' (#113) from issue111 into main
Some checks failed
Release / Build-and-test-development (push) Has been cancelled
Release / release (push) Has been cancelled
Release / Build-production-and-ng-test (push) Has been cancelled
Reviewed-on: #113
2024-06-07 15:22:00 +00:00
3584aa35c7 chore: package-locks
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m49s
2024-06-07 17:07:23 +02:00
b553520abe style: lint, package-locks
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 55s
2024-06-07 16:58:04 +02:00
e32d44b1bc fix: terms and conditions colours, editor on smaller screens show only icons
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 52s
2024-06-07 16:34:47 +02:00
105da1503f chore(release): 6.10.0 [skip ci]
# [6.10.0](https://git.datacontroller.io/dc/dc/compare/v6.9.0...v6.10.0) (2024-06-07)

### Features

* updated handsontable to v14 ([2f8d0b7](2f8d0b764a))
2024-06-07 08:58:45 +00:00
29298072e5 Merge pull request 'feat: updated handsontable to v14' (#110) from handonstable-14 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m39s
Release / Build-and-test-development (push) Successful in 8m44s
Release / release (push) Successful in 10m9s
Reviewed-on: #110
2024-06-07 08:40:54 +00:00
154c10fee5 chore: licence checker
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m50s
2024-06-07 09:45:10 +02:00
7853f7cb6a Merge branch 'main' into handonstable-14
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m32s
2024-05-31 11:39:14 +00:00
e54ecc8a35 chore(release): 6.9.0 [skip ci]
# [6.9.0](https://git.datacontroller.io/dc/dc/compare/v6.8.5...v6.9.0) (2024-05-31)

### Bug Fixes

* added colors.scss file, start of a refactor ([110ad9a](110ad9a6e9))
* added stealFocus directive ([9a79f37](9a79f37bf1))

### Features

* added app settings service to handle theme persistance, fix: optimised dark mode contrast ([35844e0](35844e0cf1))
* **dark mode:** clarity optimizations ([afa7e38](afa7e380aa))
* **dark mode:** lineage and metadata ([27907ed](27907ed00f))
* **dark mode:** refactoring clarity to enable dark mode, added toggle button ([5564aea](5564aea9c2))
* **dark mode:** removing custom css rules so clarity can handle dark/light modes. Handsontable css for dark mode ([2c0afd0](2c0afd0268))
2024-05-31 09:38:30 +00:00
d8b95c5739 Merge pull request 'Dark Mode' (#102) from issue98 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m35s
Release / Build-and-test-development (push) Successful in 8m31s
Release / release (push) Successful in 9m57s
Reviewed-on: #102
Reviewed-by: yury <yury@4gl.io>
2024-05-31 09:21:07 +00:00
2f8d0b764a feat: updated handsontable to v14
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m17s
2024-05-30 23:35:05 +02:00
d7732ed206 ci: fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m42s
2024-05-30 15:57:18 +02:00
6e631cd9a5 ci: fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m43s
2024-05-30 15:53:51 +02:00
0a9e5dd834 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m13s
2024-05-30 15:49:46 +02:00
d14a4eaadd ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m14s
2024-05-30 14:56:55 +02:00
5f7c7fcc7b ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m13s
2024-05-30 14:52:53 +02:00
978f152ab6 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m39s
2024-05-30 14:46:10 +02:00
68a2a606f3 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m14s
2024-05-30 14:22:01 +02:00
bad43135d7 chore: sheet crypto package fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m16s
2024-05-30 14:11:54 +02:00
110ad9a6e9 fix: added colors.scss file, start of a refactor
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m15s
2024-05-30 12:03:09 +02:00
e98f288302 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m16s
2024-05-30 09:47:38 +02:00
9a79f37bf1 fix: added stealFocus directive 2024-05-30 09:47:08 +02:00
85909cfc1e chore: prettier version
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m16s
2024-05-29 16:26:27 +02:00
4330da520f style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m17s
2024-05-29 16:21:56 +02:00
27907ed00f feat(dark mode): lineage and metadata 2024-05-29 16:21:28 +02:00
31c90f3190 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m15s
2024-05-29 14:36:17 +02:00
35844e0cf1 feat: added app settings service to handle theme persistance, fix: optimised dark mode contrast 2024-05-29 14:35:43 +02:00
afa7e380aa feat(dark mode): clarity optimizations
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 50s
2024-05-28 21:17:37 +02:00
cb9a5f0eb4 Merge branch 'main' into issue98
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 51s
2024-05-23 14:17:18 +00:00
da522c557d chore(git): Merge branch 'issue98' of ssh://git.datacontroller.io:29419/dc/dc into issue98
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 51s
2024-05-23 16:16:57 +02:00
2c0afd0268 feat(dark mode): removing custom css rules so clarity can handle dark/light modes. Handsontable css for dark mode 2024-05-23 16:16:47 +02:00
20255c69c2 chore(release): 6.8.5 [skip ci]
## [6.8.5](https://git.datacontroller.io/dc/dc/compare/v6.8.4...v6.8.5) (2024-05-23)

### Bug Fixes

* bitemporal load issue [#105](#105) ([967698e](967698e4ce))
2024-05-23 11:34:51 +00:00
74f1c5416b Merge pull request 'fix: bitemporal load issue #105' (#108) from issue105 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m43s
Release / Build-and-test-development (push) Successful in 8m40s
Release / release (push) Successful in 10m6s
Reviewed-on: #108
2024-05-23 11:08:03 +00:00
feed7f1ded Merge branch 'main' into issue105
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m44s
2024-05-23 11:07:29 +00:00
967698e4ce fix: bitemporal load issue #105
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m49s
2024-05-23 12:07:11 +01:00
71bd81ae47 chore(release): 6.8.4 [skip ci]
## [6.8.4](https://git.datacontroller.io/dc/dc/compare/v6.8.3...v6.8.4) (2024-05-22)

### Bug Fixes

* new approach to fixing [#105](#105) ([c11bd9a](c11bd9a2c5))
2024-05-22 16:56:15 +00:00
89a5153bb3 Merge pull request 'fix: new approach to fixing #105' (#106) from issue105 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m44s
Release / Build-and-test-development (push) Successful in 8m42s
Release / release (push) Successful in 10m14s
Reviewed-on: #106
2024-05-22 16:33:29 +00:00
c11bd9a2c5 fix: new approach to fixing #105
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m54s
2024-05-22 17:33:04 +01:00
59d46a9926 Merge branch 'main' into issue98
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 51s
2024-05-22 11:30:29 +00:00
39c3e5411f chore(release): 6.8.3 [skip ci]
## [6.8.3](https://git.datacontroller.io/dc/dc/compare/v6.8.2...v6.8.3) (2024-05-09)

### Bug Fixes

* updating core to increase filename length, closes [#103](#103) ([ee58fd5](ee58fd5b4b))
2024-05-09 11:47:48 +00:00
aad419c55d Merge pull request 'fix: updating core to increase filename length, closes #103' (#104) from issue103 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m48s
Release / Build-and-test-development (push) Successful in 8m51s
Release / release (push) Successful in 10m9s
Reviewed-on: #104
2024-05-09 11:29:37 +00:00
^
ee58fd5b4b fix: updating core to increase filename length, closes #103
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 5m2s
2024-05-09 12:23:04 +01:00
5564aea9c2 feat(dark mode): refactoring clarity to enable dark mode, added toggle button
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 51s
2024-05-08 16:51:01 +02:00
aedd2c451b Merge pull request 'release-ci' (#100) from release-ci into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 5m1s
Release / Build-and-test-development (push) Successful in 8m54s
Release / release (push) Failing after 4m31s
Reviewed-on: #100
2024-05-06 21:33:57 +00:00
6d597611b6 chore(git): Merge branch 'main' into release-ci
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m9s
2024-05-06 09:04:34 +02:00
9ffe5efe5d ci: added viya.json to the release assets 2024-05-06 09:04:19 +02:00
2715950d86 chore(release): 6.8.2 [skip ci]
## [6.8.2](https://git.datacontroller.io/dc/dc/compare/v6.8.1...v6.8.2) (2024-05-03)

### Bug Fixes

* dc_request_logs option feature ([93758ef](93758efb27))
* release process ([c0dc919](c0dc9191e3))
2024-05-03 07:19:26 +00:00
77a7190f4d ci: fixing release script
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 3m58s
Release / Build-and-test-development (push) Successful in 7m39s
Release / release (push) Successful in 8m23s
2024-05-03 09:03:56 +02:00
cc65890fea Merge pull request 'fix: dc_request_logs option feature closes #96' (#97) from issue96 into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m58s
Release / Build-and-test-development (push) Successful in 7m52s
Release / release (push) Failing after 1m18s
Reviewed-on: #97
2024-05-02 22:25:29 +00:00
^
93758efb27 fix: dc_request_logs option feature
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m3s
see: https://docs.datacontroller.io/dcc-options/#dc_request_logs
2024-05-02 23:09:14 +01:00
c0dc9191e3 fix: release process
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m57s
Release / Build-and-test-development (push) Successful in 7m44s
Release / release (push) Failing after 1m17s
2024-05-02 18:41:25 +02:00
485783a782 chore(release): 6.8.1 [skip ci]
## [6.8.1](https://git.datacontroller.io/dc/dc/compare/v6.8.0...v6.8.1) (2024-05-02)

### Bug Fixes

* hide approve button when table revertable ([ec0f539](ec0f539a33))
2024-05-02 16:10:44 +00:00
ee07bef2b8 Merge pull request 'fix: hide approve button when table revertable' (#95) from ci-fix into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m59s
Release / Build-and-test-development (push) Successful in 7m45s
Release / release (push) Failing after 1m55s
Reviewed-on: #95
2024-05-02 15:57:22 +00:00
0de8481314 ci: ng build
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m4s
2024-05-02 17:48:30 +02:00
ec0f539a33 fix: hide approve button when table revertable
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 2m1s
2024-05-02 17:44:53 +02:00
173ee2daff chore(release): 6.8.0 [skip ci]
# [6.8.0](https://git.datacontroller.io/dc/dc/compare/v6.7.0...v6.8.0) (2024-05-02)

### Bug Fixes

* ci sheet lib, submit message auto focus ([c5e4650](c5e4650327))
* **clarity:** new version style issues ([8c7de5a](8c7de5aad7))
* cypress tests ([3dd85cc](3dd85cc60b))
* ensuring that only restorable versions are restorable ([a402856](a4028562ce))
* ensuring version history only includes loaded versions ([51ebd25](51ebd25aa3))
* final testing on restore feature ([297a84d](297a84d3a4))
* issue with multiple adds/deletes, [#84](#84) ([904ca30](904ca30f91))
* load_ref var ([aaad9f7](aaad9f7207))
* removing alerts dummy data, closes [#93](#93) ([eba21e9](eba21e96b4))
* restore table version improvement ([549f357](549f35766b))
* **sas:** viewer versions fix ([c6595c1](c6595c1f61))
* stage and approve buttons renaming ([ef81e33](ef81e33f70))
* supporting SCD2 data reversions ([fa8396f](fa8396f039))
* table info modal, versions - column names ([801c8c6](801c8c6a9f))
* **updates:** angular, clarity, resolved legacy-peer-deps ([c60dd65](c60dd65a16))

### Features

* backend to show in getchangeinfo whether a user is allowed to restore ([8769841](8769841f08))
* list versions of target tables (backend) ([f8a14d4](f8a14d4bde))
* restore ([604c2e7](604c2e70bd))
* SAS services & tests for RESTORE, [#84](#84) ([9ad7ae4](9ad7ae47b5))
* staging page, restore buttons ([02a8a1c](02a8a1c565))
* table metadata modal, versions tab (and link) ([b27fea5](b27fea5b91))
* **versions:** getting list of versions (plus test) ([8003da9](8003da94e6))
2024-05-02 12:08:05 +00:00
5c0091b5e8 chore: test workaround
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m58s
Release / Build-and-test-development (push) Successful in 7m44s
Release / release (push) Failing after 1m55s
2024-05-02 13:54:44 +02:00
84dce7f6e8 Merge pull request 'Restore Previous State / Data Rollback' (#94) from restore into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 4m1s
Release / Build-and-test-development (push) Failing after 8m26s
Release / release (push) Has been skipped
Reviewed-on: #94
2024-05-02 11:18:28 +00:00
e8a943a35a chore: ng test
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 2m1s
2024-05-02 13:08:06 +02:00
b3171a8125 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m57s
2024-05-02 12:56:52 +02:00
d77f2eb674 chore(git): Merge branch 'deps-update' into restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m30s
2024-05-02 12:53:32 +02:00
5474fad9cc chore: package-lock
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m2s
2024-05-02 12:46:50 +02:00
3dd85cc60b fix: cypress tests 2024-05-02 12:39:07 +02:00
510e412ff2 chore: cypress tests fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-05-02 11:25:46 +02:00
3dfdccbc6b ci: sheet lib
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m2s
2024-05-02 10:04:31 +02:00
a55661548a chore: licence checker
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m2s
2024-05-02 09:59:21 +02:00
69363b37e9 ci: sheet lib
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m2s
2024-05-02 09:54:10 +02:00
2d6a753921 ci: sheet lib
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-05-02 09:52:22 +02:00
dc989e5668 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 58s
2024-05-02 09:38:43 +02:00
227ac480d5 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-05-02 09:30:23 +02:00
c5e4650327 fix: ci sheet lib, submit message auto focus
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-05-02 09:28:39 +02:00
56cf271e77 Merge branch 'main' into deps-update
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 57s
2024-04-30 17:41:54 +00:00
^
fa8396f039 fix: supporting SCD2 data reversions
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-04-30 18:39:00 +01:00
^
904ca30f91 fix: issue with multiple adds/deletes, #84
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-04-30 17:46:00 +01:00
549f35766b fix: restore table version improvement
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-04-30 15:43:17 +02:00
1589c799ec chore(git): Merge branch 'restore' of ssh://git.datacontroller.io:29419/dc/dc into restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-04-30 15:26:07 +02:00
604c2e70bd feat: restore 2024-04-30 15:25:58 +02:00
^
297a84d3a4 fix: final testing on restore feature
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 59s
2024-04-30 14:21:02 +01:00
^
aaad9f7207 fix: load_ref var
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 58s
2024-04-30 12:34:22 +01:00
^
a4028562ce fix: ensuring that only restorable versions are restorable
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 58s
2024-04-30 11:14:47 +01:00
5ab3f98855 chore(git): Merge branch 'main' into restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 59s
2024-04-30 09:04:46 +02:00
^
eba21e96b4 fix: removing alerts dummy data, closes #93
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 18s
2024-04-30 00:22:44 +01:00
^
9ad7ae47b5 feat: SAS services & tests for RESTORE, #84 2024-04-30 00:20:40 +01:00
cf54e4c8f3 Update README.md
Some checks failed
Release / Build-production-and-ng-test (push) Failing after 1m31s
Release / Build-and-test-development (push) Has been skipped
Release / release (push) Has been skipped
2024-04-23 13:06:51 +00:00
57aa6fa0fc ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 58s
2024-04-15 09:37:20 +02:00
4a01f3d490 ci: fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 57s
2024-04-12 21:37:49 +02:00
80a0db951d chore: angular testing
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m5s
2024-04-12 15:48:00 +02:00
3202cb8e08 ci: ng test fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m4s
2024-04-12 14:23:04 +02:00
ddf36230bf ci: ng test fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m4s
2024-04-12 14:06:29 +02:00
b67c2be968 chore: package json test script fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m3s
2024-04-12 13:53:35 +02:00
dc2c8da92b ci: added angular tests on PR
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m10s
2024-04-12 13:30:44 +02:00
5d6c3701d0 chore: licence checker update
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m3s
2024-04-12 13:28:18 +02:00
b024e263b4 chore: updated package-lock
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m2s
2024-04-12 13:20:08 +02:00
b706864e40 Merge pull request 'Angular and Clarity Update' (#91) from deps-update into main
Some checks failed
Release / Build-production-and-ng-test (push) Failing after 1m37s
Release / Build-and-test-development (push) Has been skipped
Release / release (push) Has been skipped
Reviewed-on: #91
2024-04-12 10:45:57 +00:00
60cc666b67 chore: licence checker
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m15s
2024-04-12 12:34:01 +02:00
efff4dd553 chore(cypress): bigger viewport size
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m1s
2024-04-12 11:48:23 +02:00
2b1dad8e48 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m2s
2024-04-12 10:51:32 +02:00
8c7de5aad7 fix(clarity): new version style issues 2024-04-12 10:51:11 +02:00
1db8bc2573 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m12s
2024-04-11 13:23:40 +02:00
c60dd65a16 fix(updates): angular, clarity, resolved legacy-peer-deps 2024-04-11 13:23:24 +02:00
f7f59a4b0a Merge pull request 'feat: Display Previous Versions' (#88) from restore into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 4m18s
Release / Build-and-test-development (push) Failing after 15m54s
Release / release (push) Has been skipped
Reviewed-on: #88
2024-04-04 13:24:25 +00:00
^
ec7615e7e3 chore: adding sheet-crypto to gitignoreg
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m5s
2024-04-03 10:56:49 +01:00
f411c33754 chore(git): Merge branch 'main' into restore
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m4s
2024-04-01 13:51:33 +02:00
79121168e4 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m4s
2024-04-01 13:50:50 +02:00
ef81e33f70 fix: stage and approve buttons renaming
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-04-01 13:37:41 +02:00
96066c66cb chore(release): 6.7.0 [skip ci]
# [6.7.0](https://git.datacontroller.io/dc/dc/compare/v6.6.4...v6.7.0) (2024-04-01)

### Features

* numeric values in hot dropdown aligned right ([9635626](963562621d))
2024-04-01 11:23:31 +00:00
b1819b776d chore(git): Merge branch 'restore' of ssh://git.datacontroller.io:29419/dc/dc into restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-04-01 13:09:34 +02:00
bd7a392ffc chore(git): Merge branch 'main' into restore 2024-04-01 13:09:27 +02:00
7997b77158 Merge pull request 'Numeric values in hot dropdown aligned right' (#86) from numeric-values-diff into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m26s
Release / Build-and-test-development (push) Successful in 8m10s
Release / release (push) Successful in 6m32s
Reviewed-on: #86
2024-04-01 11:08:53 +00:00
d1966bcdc5 chore(git): Merge branch 'main' into numeric-values-diff
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m3s
2024-04-01 12:33:43 +02:00
7b5bbe024d chore(release): 6.6.4 [skip ci]
## [6.6.4](https://git.datacontroller.io/dc/dc/compare/v6.6.3...v6.6.4) (2024-04-01)

### Bug Fixes

* ordering SOFTSELECT numerically in dropdown ([f522038](f522038b8d)), closes [#85](#85)
* reverting col ([fbbcf90](fbbcf90956))
* typo ([31d4e5c](31d4e5c727))
2024-04-01 09:51:54 +00:00
4d84f15aca Merge pull request 'ci: install sheet temporarily' (#89) from ci into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m16s
Release / Build-and-test-development (push) Successful in 8m1s
Release / release (push) Successful in 6m22s
Reviewed-on: #89
2024-04-01 09:37:56 +00:00
928937daab ci: sheet
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m4s
2024-04-01 11:14:00 +02:00
3bd8d247e5 ci: sheet
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m3s
2024-04-01 10:59:03 +02:00
cf6c9dd5f2 ci: sheet
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m0s
2024-04-01 10:55:59 +02:00
ff55cbbaad ci: sheet
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-04-01 10:45:16 +02:00
3eda4e2c58 ci: install sheet temporarily
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-04-01 10:39:30 +02:00
02a8a1c565 feat: staging page, restore buttons 2024-03-29 13:08:48 +01:00
^
8769841f08 feat: backend to show in getchangeinfo whether a user is allowed to restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-03-28 16:03:27 +00:00
7208fe1c3b chore(git): Merge branch 'restore' of ssh://git.datacontroller.io:29419/dc/dc into restore
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-03-26 19:14:53 +01:00
801c8c6a9f fix: table info modal, versions - column names 2024-03-26 19:14:41 +01:00
^
51ebd25aa3 fix: ensuring version history only includes loaded versions
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 48s
2024-03-26 14:25:58 +00:00
c6595c1f61 fix(sas): viewer versions fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 46s
2024-03-26 14:20:01 +01:00
a267666e99 style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 46s
2024-03-25 22:41:25 +01:00
b27fea5b91 feat: table metadata modal, versions tab (and link) 2024-03-25 22:41:00 +01:00
^
f8a14d4bde feat: list versions of target tables (backend)
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 47s
2024-03-25 12:37:11 +00:00
^
633e35338d chore: remove unnecessary concatenation 2024-03-20 21:38:44 +00:00
^
8003da94e6 feat(versions): getting list of versions (plus test) 2024-03-20 21:37:13 +00:00
c3af97ef57 Merge pull request 'issue85' (#87) from issue85 into main
Some checks failed
Release / Build-production-and-ng-test (push) Failing after 1m13s
Release / Build-and-test-development (push) Has been skipped
Release / release (push) Has been skipped
Reviewed-on: #87
2024-03-19 22:41:04 +00:00
31d4e5c727 fix: typo
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 47s
2024-03-19 22:36:00 +00:00
fbbcf90956 fix: reverting col 2024-03-19 22:35:16 +00:00
f522038b8d fix: ordering SOFTSELECT numerically in dropdown
Closes #85
2024-03-19 22:33:39 +00:00
ace599b39f style: lint
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 46s
2024-03-19 10:01:30 +01:00
963562621d feat: numeric values in hot dropdown aligned right
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 29s
2024-03-18 17:32:29 +01:00
5171d07441 chore(release): 6.6.3 [skip ci]
## [6.6.3](https://git.datacontroller.io/dc/dc/compare/v6.6.2...v6.6.3) (2024-02-26)

### Bug Fixes

* allow empty clause value when NE or CONTAINS ([432450a](432450a15b))
2024-02-26 14:17:24 +00:00
9a0b9573d5 Merge pull request 'Allow empty clause value when operator is NE or CONTAINS' (#83) from issue-82 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m18s
Release / Build-and-test-development (push) Successful in 7m46s
Release / release (push) Successful in 6m18s
Reviewed-on: #83
2024-02-26 14:03:36 +00:00
4733311ef3 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m0s
2024-02-26 14:15:34 +01:00
432450a15b fix: allow empty clause value when NE or CONTAINS 2024-02-26 14:14:51 +01:00
47638becc0 chore(release): 6.6.2 [skip ci]
## [6.6.2](https://git.datacontroller.io/dc/dc/compare/v6.6.1...v6.6.2) (2024-02-22)

### Bug Fixes

* excel with commas getting wrapped in quotes ([3860134](38601346a5))
2024-02-22 12:33:10 +00:00
bdd3a95685 Merge pull request 'excel with commas getting wrapped in quotes' (#80) from issue-77 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m13s
Release / Build-and-test-development (push) Successful in 7m44s
Release / release (push) Successful in 6m15s
Reviewed-on: #80
Reviewed-by: sabir <sabir@4gl.io>
2024-02-22 12:19:34 +00:00
38601346a5 fix: excel with commas getting wrapped in quotes
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 15s
2024-02-21 14:48:42 +01:00
dc3a6ae6a1 chore(release): 6.6.1 [skip ci]
## [6.6.1](https://git.datacontroller.io/dc/dc/compare/v6.6.0...v6.6.1) (2024-02-19)

### Bug Fixes

* **client:** bumped @sasjs/adapter with fixed redirected login ([eb1c09d](eb1c09d790))
2024-02-19 13:38:12 +00:00
f668b1e7f7 Merge pull request 'fix(client): bumped @sasjs/adapter with fixed redirected login' (#79) from @sasjs/adapter-bump into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m53s
Release / Build-and-test-development (push) Successful in 8m34s
Release / release (push) Successful in 7m2s
Reviewed-on: #79
Reviewed-by: mihajlo <mihajlo@4gl.io>
2024-02-19 13:22:56 +00:00
eb1c09d790 fix(client): bumped @sasjs/adapter with fixed redirected login
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m6s
2024-02-19 16:16:30 +03:00
9bf324c74b chore(release): 6.6.0 [skip ci]
# [6.6.0](https://git.datacontroller.io/dc/dc/compare/v6.5.2...v6.6.0) (2024-02-12)

### Bug Fixes

* adjust the col numbers in extracted data ([cff5989](cff5989559))

### Features

* extra table metadata for [#75](#75) ([837821f](837821fd01))
* show dsnote on hover title ([6565834](6565834ad4))
2024-02-12 11:30:37 +00:00
f13e909478 Merge pull request 'fix: adjust the col numbers in extracted data' (#76) from fix-complex-xl-upload into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m53s
Release / Build-and-test-development (push) Successful in 8m34s
Release / release (push) Successful in 7m0s
Reviewed-on: #76
2024-02-12 09:58:42 +00:00
6a0fe287dd chore: add comment
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m4s
2024-02-12 14:53:53 +05:00
5a48f2e6e3 chore: lint fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m5s
2024-02-12 12:51:08 +05:00
6565834ad4 feat: show dsnote on hover title
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 18s
2024-02-12 11:30:59 +05:00
837821fd01 feat: extra table metadata for #75
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-02-09 19:02:24 +00:00
cff5989559 fix: adjust the col numbers in extracted data
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 18s
2024-02-09 18:37:25 +05:00
60510a4d68 chore(release): 6.5.2 [skip ci]
## [6.5.2](https://git.datacontroller.io/dc/dc/compare/v6.5.1...v6.5.2) (2024-02-06)

### Bug Fixes

* ordering mpe_selectbox data by the data values after selectbox_order ([2b54034](2b54034973))
2024-02-06 18:55:05 +00:00
2b54034973 fix: ordering mpe_selectbox data by the data values after selectbox_order
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m51s
Release / Build-and-test-development (push) Successful in 8m35s
Release / release (push) Successful in 7m2s
2024-02-06 18:39:47 +00:00
347b0f9065 chore(release): 6.5.1 [skip ci]
## [6.5.1](https://git.datacontroller.io/dc/dc/compare/v6.5.0...v6.5.1) (2024-02-02)

### Bug Fixes

* ensuring submitter email can be pulled from mpe_emails ([eac0104](eac0104d7a))
2024-02-02 11:35:49 +00:00
eac0104d7a fix: ensuring submitter email can be pulled from mpe_emails
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m46s
Release / Build-and-test-development (push) Successful in 8m34s
Release / release (push) Successful in 6m51s
2024-02-02 11:20:43 +00:00
1c8e4604de chore(release): 6.5.0 [skip ci]
# [6.5.0](https://git.datacontroller.io/dc/dc/compare/v6.4.0...v6.5.0) (2024-01-26)

### Features

* filtering by reference to Variables as well as Values ([6eb1aa8](6eb1aa85d2))
2024-01-26 10:55:18 +00:00
e9624635ed Merge pull request 'feat: Filtering with variable as well as values' (#70) from issue-68 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m42s
Release / Build-and-test-development (push) Successful in 8m27s
Release / release (push) Successful in 6m47s
Reviewed-on: #70
2024-01-26 10:40:29 +00:00
f9beda1ddb chore: lint fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m4s
2024-01-26 09:22:50 +05:00
53400de110 chore: quick fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-25 18:24:01 +05:00
cf37ddab22 Merge branch 'main' into issue-68
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-25 11:34:20 +00:00
625af199f4 chore(release): 6.4.0 [skip ci]
# [6.4.0](https://git.datacontroller.io/dc/dc/compare/v6.3.1...v6.4.0) (2024-01-24)

### Bug Fixes

* add dcLib to globals ([5d93346](5d93346b52))
* add service to get xlmap rules and fixed interface name ([9ffa30a](9ffa30ab74))
* increasing length of mpe_excel_map cols to ([2d4d068](2d4d068413))
* providing info on mapids to FE ([fd94945](fd94945466))
* removing tables from EDIT menu that are in xlmaps ([9550ae4](9550ae4d11))
* removing XLMAP_TARGETLIBDS from mpe_xlmaps_rules table ([93702c6](93702c63dc))
* renaming TABLE macvar to LOAD_REF in postdata.sas ([01915a2](01915a2db9))
* reverting xlmap in getdata change ([2d6e747](2d6e747db9))
* update edit tab to load ([516e5a2](516e5a2062))

### Features

* adding ability to define the target table for excel maps ([c86fba9](c86fba9dc7))
* adding ismap attribute to getdata response (and fixing test) ([2702bb3](2702bb3c84))
* Complex Excel Uploads ([cf19381](cf19381060)), closes [#69](#69)
* Create Tables / Files dropdown under load tab ([b473b19](b473b198a6))
* display list of maps in sidebar ([5aec024](5aec024242))
* implemented the logic for xlmap component ([50696bb](50696bb926))
* model changes for [#69](#69) ([271543a](271543a446))
* new getxlmaps service to return rules for a particular xlmap_id ([56264ec](56264ecc69))
* validating the excel map after stage (adding load-ref) ([a485c3b](a485c3b787))
2024-01-24 17:50:00 +00:00
56e9217f4b Merge pull request 'ci: semantic release requires node 20 or above' (#74) from ci-deploy into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m48s
Release / Build-and-test-development (push) Successful in 8m32s
Release / release (push) Successful in 7m1s
Reviewed-on: #74
2024-01-24 17:34:51 +00:00
86f1af7926 Merge branch 'main' into ci-deploy
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-24 17:34:21 +00:00
7737f8455d ci: semantic release requires node 20 or above
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-24 18:33:50 +01:00
b0f1677fcc Merge pull request 'Fixed mocked startupservice used for cypress testing' (#73) from ci-deploy into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 4m47s
Release / Build-and-test-development (push) Successful in 8m35s
Release / release (push) Failing after 1m46s
Reviewed-on: #73
2024-01-24 16:40:02 +00:00
4406e0d4b4 ci: fixed mocked startupservice used for cypress testing
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-01-24 17:34:07 +01:00
cf19381060 feat: Complex Excel Uploads
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 4m49s
Release / release (push) Has been skipped
Release / Build-and-test-development (push) Failing after 9m24s
Reviewed-on: #71

Closes #69
2024-01-24 13:48:07 +00:00
802d8a3b08 Merge branch 'main' into issue-68
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-24 13:47:24 +00:00
2a852496e9 chore: add specs
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-24 17:05:18 +05:00
4653097225 chore: move utils to separate file
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 23s
2024-01-24 15:30:22 +05:00
8afee29e02 chore: limit submitting rows based on liscence
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-24 14:28:56 +05:00
233eca39ef chore: move utility functions to separate file
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-01-24 14:10:11 +05:00
1a96bb1233 chore: show variables in dropdown instead of values when variable is selected
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 16s
2024-01-24 10:40:33 +05:00
93702c63dc fix: removing XLMAP_TARGETLIBDS from mpe_xlmaps_rules table
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 17s
2024-01-23 16:54:44 +00:00
df065562d1 chore: bumping core
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m9s
2024-01-23 12:10:18 +00:00
802c99adf9 chore: fix .npmrc
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-22 10:30:19 +00:00
482c7455f5 chore: fix the logic for goback button in stage component
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-19 21:03:34 +05:00
731b96dccc chore: modifired xlmaps array in global variables
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2024-01-19 18:48:38 +05:00
9550ae4d11 fix: removing tables from EDIT menu that are in xlmaps
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-19 11:12:31 +00:00
2d6e747db9 fix: reverting xlmap in getdata change
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2024-01-19 10:52:39 +00:00
fd94945466 fix: providing info on mapids to FE
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-18 17:39:10 +00:00
d3b0c09332 chore: in editors/loadfile service pass attached excel file too as payload
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-18 22:19:04 +05:00
01915a2db9 fix: renaming TABLE macvar to LOAD_REF in postdata.sas
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
also adding a sample post approve hook for xlmap dataloads
2024-01-18 16:31:11 +00:00
51b043b6d2 chore: postedit hook example updates
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-18 15:43:48 +00:00
c144fd8087 chore: fixed hanging state after getting error in upload and submit
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-18 18:39:23 +05:00
12b15df78c chore: move to data tab after extracting data
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-17 22:38:26 +05:00
d6ecd12cea chore: added tab view in xlmap component
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2024-01-17 22:33:42 +05:00
1c3d498da6 chore: wording of rules page
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2024-01-17 11:23:07 +00:00
d75e10aef5 chore: quick fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-16 15:25:52 +05:00
f0f9d85558 chore: quick fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-16 14:27:44 +05:00
86f3411896 Merge pull request 'feat: complex excel upload (UI)' (#72) from issue-69-ui into issue69
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
Reviewed-on: #72
2024-01-16 09:16:43 +00:00
6daef39268 chore: add modal for displaying submit limit notice
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-16 13:56:47 +05:00
7d1720a360 Merge branch 'issue69' into issue-69-ui
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-16 08:47:47 +00:00
b11a4884b4 chore: quick fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2024-01-16 13:00:15 +05:00
50696bb926 feat: implemented the logic for xlmap component
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-16 12:21:45 +05:00
d67d4e2f86 chore: added xlmap.module.ts file 2024-01-16 12:19:52 +05:00
2f01c4d251 chore: added xlmap routing component 2024-01-16 12:17:42 +05:00
9ffa30ab74 fix: add service to get xlmap rules and fixed interface name 2024-01-16 12:14:28 +05:00
5d93346b52 fix: add dcLib to globals 2024-01-16 12:08:42 +05:00
39762b36c6 chore: updated workspace settings 2024-01-16 12:04:39 +05:00
e40ebdff05 Merge branch 'main' into issue69
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-12 13:09:39 +00:00
8d12d9e51e chore: fixing validations
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-11 18:48:13 +00:00
23708c9aae chore: fix xlmap validation logic
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2024-01-11 18:28:51 +00:00
c86fba9dc7 feat: adding ability to define the target table for excel maps
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-11 18:11:22 +00:00
e747e6e4e7 chore: additional xlmaps to cover LASTDOWN and BLANKROW scenarios
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2024-01-11 14:44:13 +00:00
5aec024242 feat: display list of maps in sidebar
implemented routing module/component for home-routing
2024-01-04 11:33:38 +05:00
b473b198a6 feat: Create Tables / Files dropdown under load tab 2024-01-04 11:28:16 +05:00
516e5a2062 fix: update edit tab to load 2024-01-04 11:26:13 +05:00
fb3abbe491 chore: update workspace settings 2024-01-04 11:24:39 +05:00
3e009f3037 chore: adding migration for new tables
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-03 12:12:38 +00:00
e63d304953 chore(release): 6.3.1 [skip ci]
## [6.3.1](https://git.datacontroller.io/dc/dc/compare/v6.3.0...v6.3.1) (2024-01-01)

### Bug Fixes

* enabling excel uploads to tables with retained keys, also adding more validation to MPE_TABLES updates ([3efccc4](3efccc4cf3))
2024-01-01 17:53:14 +00:00
3cd90c2d47 Merge pull request 'fix: enabling excel uploads to tables with retained keys, also adding more validation to MPE_TABLES updates' (#67) from dcfixes into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 3m11s
Release / Build-and-test-development (push) Successful in 6m31s
Release / release (push) Successful in 5m16s
Reviewed-on: #67
2024-01-01 17:42:07 +00:00
a485c3b787 feat: validating the excel map after stage (adding load-ref)
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-01 16:53:50 +00:00
2702bb3c84 feat: adding ismap attribute to getdata response (and fixing test)
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-01 16:07:47 +00:00
56264ecc69 feat: new getxlmaps service to return rules for a particular xlmap_id
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-01 14:50:02 +00:00
cc4535245c chore: adding xlmaps in startupservice response, #69
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-01 14:10:49 +00:00
6ae31de1dd chore: adding sample data for basel KM1 template
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2024-01-01 13:54:08 +00:00
2d4d068413 fix: increasing length of mpe_excel_map cols to
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2024-01-01 12:23:07 +00:00
271543a446 feat: model changes for #69
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 47s
2023-12-27 16:57:48 +01:00
8f796aec36 chore(git): Merge branch 'main' into issue-68
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2023-12-26 21:09:16 +01:00
6eb1aa85d2 feat: filtering by reference to Variables as well as Values 2023-12-26 21:08:58 +01:00
ac59b77ad5 Merge branch 'main' into dcfixes
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 46s
2023-12-12 08:30:25 +00:00
3efccc4cf3 fix: enabling excel uploads to tables with retained keys, also adding more validation to MPE_TABLES updates
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 13s
2023-12-12 08:27:45 +00:00
8cbcd18f4b chore(release): 6.3.0 [skip ci]
# [6.3.0](https://git.datacontroller.io/dc/dc/compare/v6.2.8...v6.3.0) (2023-12-04)

### Features

* viewer row handle ([dadac4f](dadac4f13f))
2023-12-04 18:49:31 +00:00
6bb2378790 Merge pull request 'ci: doxygen fix' (#66) from ci-fix into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 3m8s
Release / Build-and-test-development (push) Successful in 6m27s
Release / release (push) Successful in 5m23s
Reviewed-on: #66
2023-12-04 18:38:27 +00:00
e7d0ffe8c0 Merge branch 'main' into ci-fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 48s
2023-12-04 17:38:00 +00:00
ab89600c73 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 47s
2023-12-04 18:37:05 +01:00
830e3816a0 ci: build, syntax fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2023-12-04 18:32:17 +01:00
dadac4f13f feat: viewer row handle
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 0s
2023-12-04 18:17:49 +01:00
1de48a49af ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 0s
2023-12-04 17:06:18 +01:00
687a1e1cb5 ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 33s
2023-12-04 17:02:08 +01:00
665a04f5c5 ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 14s
2023-12-04 17:01:26 +01:00
fdb18d242b ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 19s
2023-12-04 14:47:30 +01:00
ec173da4ce ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 9s
2023-12-04 14:47:02 +01:00
bb35cc15d2 ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 8s
2023-12-04 14:46:32 +01:00
181f52eaea ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 8s
2023-12-04 14:45:57 +01:00
fc7c8101ed ci: doxygen fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 8s
2023-12-04 14:44:49 +01:00
a347603fe0 chore(release): 6.2.8 [skip ci]
## [6.2.8](https://git.datacontroller.io/dc/dc/compare/v6.2.7...v6.2.8) (2023-12-04)

### Bug Fixes

* bumping sasjs/core to fix mp_loadformat issue ([a1d308e](a1d308ea07))
* new logic for -fc suffix.  Closes [#63](#63) ([5579db0](5579db0eaf))
2023-12-04 11:51:52 +00:00
09022c995f chore: prettier fix
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m5s
Release / Build-and-test-development (push) Successful in 6m15s
Release / release (push) Failing after 4m56s
2023-12-04 12:41:04 +01:00
3609943f30 Merge pull request 'fix: new logic for -fc suffix, plus fixes for format record additions / deletions' (#64) from dcfixes into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m5s
Release / Build-and-test-development (push) Failing after 7m12s
Release / release (push) Has been skipped
Reviewed-on: #64
2023-12-03 13:56:26 +00:00
a1d308ea07 fix: bumping sasjs/core to fix mp_loadformat issue
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 12s
2023-12-03 13:53:53 +00:00
5579db0eaf fix: new logic for -fc suffix. Closes #63
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 52s
2023-12-03 11:19:40 +00:00
3a3e488b23 chore: updating yaml to use self-hosted doc site
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 7m20s
Release / Build-and-test-development (push) Successful in 13m43s
Release / release (push) Failing after 2m36s
2023-11-14 22:23:05 +00:00
0a82ec0a70 chore: updating link in README to releases page
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 7m50s
Release / Build-and-test-development (push) Successful in 14m11s
Release / release (push) Failing after 2m42s
2023-11-14 21:43:55 +00:00
bc1d89218e chore(release): 6.2.7 [skip ci]
## [6.2.7](https://git.datacontroller.io/dc/dc/compare/v6.2.6...v6.2.7) (2023-11-09)

### Bug Fixes

* **audit:** updated crypto-js (hashing rows in dynamic cell validation) ([a7aa42a](a7aa42a59b))
* missing dependency and avoiding label length limit issue ([91f128c](91f128c2fe))
2023-11-09 09:01:38 +00:00
817b9adeac Merge pull request 'fix(audit): updated crypto-js (hashing rows in dynamic cell validation)' (#62) from audit-fix into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 8m0s
Release / Build-and-test-development (push) Successful in 13m41s
Release / release (push) Successful in 12m7s
Reviewed-on: #62
2023-11-09 08:37:19 +00:00
a7aa42a59b fix(audit): updated crypto-js (hashing rows in dynamic cell validation)
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m45s
2023-11-09 09:20:21 +01:00
34f239036d Merge pull request 'fix: missing dependency and avoiding label length limit issue' (#61) from corebump into main
Some checks failed
Release / Build-production-and-ng-test (push) Failing after 2m51s
Release / Build-and-test-development (push) Has been skipped
Release / release (push) Has been skipped
Reviewed-on: #61
2023-11-08 21:45:25 +00:00
91f128c2fe fix: missing dependency and avoiding label length limit issue
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m43s
Relates to the following core issues:
* https://github.com/sasjs/core/issues/364
* https://github.com/sasjs/core/issues/363
2023-11-08 21:36:17 +00:00
a00ebea692 chore(release): 6.2.6 [skip ci]
## [6.2.6](https://git.datacontroller.io/dc/dc/compare/v6.2.5...v6.2.6) (2023-10-18)

### Bug Fixes

* bumping core to address mm_assigndirectlib issue ([c27cdab](c27cdab3fc))
2023-10-18 10:48:48 +00:00
c27cdab3fc fix: bumping core to address mm_assigndirectlib issue
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 7m19s
Release / Build-and-test-development (push) Successful in 11m45s
Release / release (push) Successful in 11m9s
2023-10-18 11:26:29 +01:00
d7da2d7890 chore(release): 6.2.5 [skip ci]
## [6.2.5](https://git.datacontroller.io/dc/dc/compare/v6.2.4...v6.2.5) (2023-10-17)

### Bug Fixes

* enabling AUTHDOMAIN in MM_ASSIGNDIRECTLIB ([008b45a](008b45ad17))
2023-10-17 16:06:19 +00:00
76f0fd4232 Merge pull request 'fix: enabling AUTHDOMAIN in MM_ASSIGNDIRECTLIB for ODBC Engines' (#60) from issue59 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 7m8s
Release / Build-and-test-development (push) Successful in 11m34s
Release / release (push) Successful in 10m54s
Reviewed-on: #60
2023-10-17 15:44:34 +00:00
008b45ad17 fix: enabling AUTHDOMAIN in MM_ASSIGNDIRECTLIB
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m19s
Bumped sasjs/core to 4.48.1
2023-10-17 16:42:05 +01:00
4d49263816 chore(release): 6.2.4 [skip ci]
## [6.2.4](https://git.datacontroller.io/dc/dc/compare/v6.2.3...v6.2.4) (2023-10-16)

### Bug Fixes

* Enable display of metadata-only tables. Closes [#56](#56) ([f3e82b4](f3e82b4ee2))
2023-10-16 16:38:06 +00:00
6a2482e5c6 Merge pull request 'fix: Enable display of metadata-only tables. Closes #56' (#57) from issue56 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 7m19s
Release / Build-and-test-development (push) Successful in 11m26s
Release / release (push) Successful in 11m9s
Reviewed-on: #57
2023-10-16 15:10:04 +00:00
b5c3fb2af4 Merge branch 'main' into issue56
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m18s
2023-10-16 14:55:11 +00:00
fa2c8eb839 Merge pull request 'Adding cypress videos to the artifacts' (#58) from ci into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 7m5s
Release / Build-and-test-development (push) Successful in 11m21s
Release / release (push) Failing after 2m6s
Reviewed-on: #58
2023-10-16 14:24:10 +00:00
f3e82b4ee2 fix: Enable display of metadata-only tables. Closes #56
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m21s
2023-10-16 15:21:01 +01:00
ba67248155 chore: adding cypress videos to the artifacts
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m21s
2023-10-16 16:11:56 +02:00
a6d962bfaa Merge pull request 'Downgrading SheetJS' (#55) from sheetjs-downgrade into main
Some checks reported warnings
Release / Build-production-and-ng-test (push) Has been cancelled
Release / Build-and-test-development (push) Has been cancelled
Release / release (push) Has been cancelled
Reviewed-on: #55
2023-10-16 10:48:02 +00:00
95cddb52d4 chore: package-lock
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m22s
2023-10-16 12:40:17 +02:00
5a5118d775 chore: downgrading sheetjs
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 27s
2023-10-16 12:34:30 +02:00
1b1cdd7a4b Merge pull request 'Removing development branch jobs, moving test jobs to the release pipeline' (#54) from discard-development into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 7m9s
Release / Build-and-test-development (push) Failing after 14m17s
Release / release (push) Has been skipped
Reviewed-on: #54
2023-10-16 09:46:34 +00:00
a9ddf7f7dd chore: removing development branch JOBS, moving test jobs to the release pipeline
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m23s
2023-10-13 11:24:42 +02:00
b54b3f1778 chore(release): 6.2.3 [skip ci]
## [6.2.3](https://git.datacontroller.io/dc/dc/compare/v6.2.2...v6.2.3) (2023-10-12)

### Bug Fixes

* bumping core library to avoid non-ascii char in mp_validatecols.sas. [#50](#50) ([11b06f6](11b06f6416))
* removing copyright symbol from mpe_alerts macro. [#50](#50) ([adb7eb7](adb7eb7755))
2023-10-12 09:42:44 +00:00
349a63c591 Merge pull request 'fix: removing non-ascii chars from SAS program headers' (#51) from issue50 into main
All checks were successful
Release / release (push) Successful in 11m21s
Reviewed-on: #51
2023-10-12 09:40:30 +00:00
293d33912f Merge pull request 'development' (#52) from development into issue50
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Has been cancelled
Reviewed-on: #52
2023-10-12 09:38:43 +00:00
357b9849e7 Merge branch 'issue50' into development
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-production-and-ng-test (push) Has been cancelled
2023-10-12 09:38:19 +00:00
0c8a9eef32 chore(ci): build and ng test fix
Some checks failed
Test / Build-production-and-ng-test (push) Successful in 7m30s
Test / Build-and-test-development (push) Failing after 14m29s
Test / Build-and-test-development-latest-adapter (push) Failing after 14m45s
Build / Build-and-ng-test (pull_request) Successful in 1m25s
2023-10-12 08:33:31 +02:00
112b1d0da4 chore(ci): audit check fix
Some checks failed
Test / Build-production-and-ng-test (push) Failing after 2m22s
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
2023-10-12 08:26:35 +02:00
a05007416a chore(ci): audit check fix
Some checks failed
Test / Build-production-and-ng-test (push) Failing after 2m25s
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
2023-10-12 08:21:58 +02:00
9f7dd55583 Merge pull request 'Release fix' (#49) from release-fix into development
Some checks failed
Test / Build-production-and-ng-test (push) Failing after 2m36s
Test / Build-and-test-development (push) Failing after 14m29s
Test / Build-and-test-development-latest-adapter (push) Failing after 14m30s
Reviewed-on: #49
2023-10-11 22:02:20 +00:00
11b06f6416 fix: bumping core library to avoid non-ascii char in mp_validatecols.sas. #50
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m30s
2023-10-11 22:57:07 +01:00
adb7eb7755 fix: removing copyright symbol from mpe_alerts macro. #50 2023-10-11 22:56:14 +01:00
b776b80728 chore: making semantic-release fail if no release available
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m17s
2023-10-11 16:34:06 +02:00
73a149ea7b chore: updated contributing.md with release instructions
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m18s
2023-10-09 13:02:13 +02:00
ef8784093b chore: release is draft fix, release will update package.json version
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m18s
2023-10-09 12:46:17 +02:00
b30c788e3d chore(release): 6.2.2 [skip ci]
## [6.2.2](https://git.datacontroller.io/dc/dc/compare/v6.2.1...v6.2.2) (2023-10-09)

### Bug Fixes

* updated SheetJS (crypto) to the latest ([8bd0dd2](8bd0dd22c2))
2023-10-09 09:52:20 +00:00
23899bdff3 Merge pull request 'fix: updated SheetJS (crypto) to the latest' (#48) from development into main
All checks were successful
Release / release (push) Successful in 11m13s
Reviewed-on: #48
2023-10-09 09:49:16 +00:00
8bd0dd22c2 fix: updated SheetJS (crypto) to the latest
Some checks reported warnings
Test / Build-production-and-ng-test (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Build / Build-and-ng-test (pull_request) Successful in 1m19s
2023-10-09 11:47:27 +02:00
c55b00c74f chore(release): 6.2.1 [skip ci]
Some checks failed
Test / Build-production-and-ng-test (push) Failing after 2m3s
Test / Build-and-test-development (push) Successful in 11m49s
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-09)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* closes [#39](#39) upcase issue in MPE_SECURITY ([a00d31c](a00d31caf3))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-10-09 09:03:58 +00:00
c895f509b0 Merge pull request 'chore: fixed CI, trigger pending release' (#47) from development into main
All checks were successful
Release / release (push) Successful in 11m20s
Reviewed-on: #47
2023-10-09 09:00:52 +00:00
5968915331 chore: fixed CI, trigger pending release
Some checks reported warnings
Test / Build-and-test-development (push) Has been cancelled
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-production-and-ng-test (push) Has been cancelled
Build / Build-and-ng-test (pull_request) Successful in 1m20s
2023-10-09 11:00:09 +02:00
44ffc082f6 chore: changelog revert to 6.2.0
Some checks reported warnings
Release / release (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-production-and-ng-test (push) Has been cancelled
2023-10-09 10:37:06 +02:00
b716ae5675 chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-08)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* closes [#39](#39) upcase issue in MPE_SECURITY ([a00d31c](a00d31caf3))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-10-08 19:33:42 +00:00
01a0b59494 Merge pull request 'package-lock re-generated for CI release to pass, fixed development branch CI yaml' (#46) from development into main
Some checks failed
Release / release (push) Failing after 6m57s
Reviewed-on: #46
2023-10-08 19:30:05 +00:00
8ebc3da0bb chore(git): Merge branch 'main' into development
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Has been cancelled
Test / Build-production-and-ng-test (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
2023-10-08 21:29:12 +02:00
133577a4fa ci: fixed development yaml
Some checks failed
Test / Build-production-and-ng-test (push) Failing after 2m3s
Test / Build-and-test-development-latest-adapter (push) Has been cancelled
Test / Build-and-test-development (push) Has been cancelled
Build / Build-and-ng-test (pull_request) Successful in 1m22s
2023-10-08 21:26:55 +02:00
a19615db41 chore: reverting 6.2.1 release
Some checks reported warnings
Release / release (push) Has been cancelled
2023-10-08 21:22:29 +02:00
32b212a6bf chore: package-lock fix 2023-10-08 21:21:35 +02:00
00ec4529cd chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-08)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* closes [#39](#39) upcase issue in MPE_SECURITY ([a00d31c](a00d31caf3))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-10-08 19:08:09 +00:00
102d03888f Merge pull request 'Release fix' (#45) from development into main
Some checks failed
Release / release (push) Failing after 7m6s
Reviewed-on: #45
2023-10-08 19:06:03 +00:00
9f8247320e Merge pull request 'Master branch sync, release procedure fixing' (#44) from master-sync into development
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m20s
Reviewed-on: #44
2023-10-08 19:03:01 +00:00
ef871de30e chore: fixing changelog
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m20s
2023-10-08 20:56:09 +02:00
b3a15ce26b chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-08)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* closes [#39](#39) upcase issue in MPE_SECURITY ([a00d31c](a00d31caf3))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-10-08 16:56:17 +00:00
270695aec2 Merge pull request 'fix: triggering release' (#43) from development into main
Some checks failed
Release / release (push) Failing after 2m9s
Reviewed-on: #43
2023-10-08 16:53:54 +00:00
ad7392a326 Merge pull request 'chore: setting legacy-peer-deps in .npmrc' (#42) from npmrc into development
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Has been cancelled
Reviewed-on: #42
2023-10-08 16:53:03 +00:00
92a50a42e2 chore: setting legacy-peer-deps in .npmrc
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m21s
2023-10-08 17:51:27 +01:00
a3a8856d8c chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-08)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* closes [#39](#39) upcase issue in MPE_SECURITY ([a00d31c](a00d31caf3))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-10-08 16:49:20 +00:00
150c19b1b0 Merge pull request 'development' (#41) from development into main
Some checks failed
Release / release (push) Failing after 2m15s
Reviewed-on: #41
2023-10-08 16:46:19 +00:00
f04c51ee4e Merge pull request 'fix: closes #39 upcase issue in MPE_SECURITY' (#40) from issue39 into development
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Has been cancelled
Reviewed-on: #40
2023-10-08 16:45:23 +00:00
c4338bf957 chore: updating tests, post edit hook, and access check macro. #39
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m22s
2023-10-08 17:42:26 +01:00
5b06f4ede8 chore: improving docs for mpe_accesscheck and adding a test for mpe_accesscheck
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m27s
2023-10-07 22:46:32 +01:00
e7ab2cc956 chore: adding mpe_security_postedit hook link in MPE_TABLES on deploy. #39
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m28s
2023-10-07 18:28:36 +01:00
5ebf8a66f7 chore: error message source file fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m19s
2023-10-07 00:16:05 +01:00
3d4e886b9b chore: adding missing dependency
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m22s
2023-10-07 00:13:48 +01:00
a00d31caf3 fix: closes #39 upcase issue in MPE_SECURITY
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m23s
adding frontend validation rule, backend upcase enforcement rule, and modification to service code to ensure values are upcased before comparison
2023-10-07 00:11:38 +01:00
40fe707287 Merge pull request 'maincopy' (#38) from maincopy into development
Reviewed-on: #38
2023-09-26 07:40:05 +00:00
8296be01ba chore: cleanup of items in changelog for v6.2.1
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m19s
2023-09-26 08:38:40 +01:00
dbeb003292 chore(release): 6.2.1 [skip ci]
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m25s
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-09-25)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-09-25 14:59:38 +00:00
f048501c48 Merge pull request 'development' (#37) from development into main
All checks were successful
Release / release (push) Successful in 11m11s
Reviewed-on: #37
2023-09-25 14:57:44 +00:00
498350b3f3 Merge pull request 'master-sync' (#36) from master-sync into development
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m18s
Reviewed-on: #36
Reviewed-by: allan <allan@4gl.io>
2023-09-25 14:55:33 +00:00
91e82c9c65 ci: npm ci in build.yaml
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 1m19s
2023-09-25 16:53:40 +02:00
24067ea82b chore: calling licence checker script as a part of PR action
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 24s
2023-09-25 16:51:33 +02:00
aa7deddba0 chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-09-25)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* handsontable v13 ([6f482ec](6f482ec6d9))
* latest adapter ([5e30dc0](5e30dc0f89))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](8571e01e44))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](#33) ([94ab949](94ab949df8))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-09-25 14:33:27 +00:00
b2d13203d1 Merge pull request 'development' (#34) from development into main
Some checks failed
Release / release (push) Failing after 2m25s
Reviewed-on: #34
2023-09-25 14:31:25 +00:00
19c1092b5b Merge pull request 'fix: latest adapter' (#32) from adapter-bump into development
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 25s
Reviewed-on: #32
2023-09-25 14:26:49 +00:00
94ab949df8 fix: updating editors/stagedata to address issues in particular viya configurations as described in issue #33
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 25s
2023-09-25 16:24:50 +02:00
9eb2451c2f chore(git): Merge branch 'adapter-bump' of ssh://git.datacontroller.io:29419/dc/dc into adapter-bump 2023-09-07 12:52:25 +02:00
6e521bfa3e chore: renaming format names due to changes in how Viya treats the last letter
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 23s
2023-09-07 11:49:29 +01:00
239720fe0c chore(git): Merge branch 'development' into adapter-bump 2023-09-07 12:13:17 +02:00
8571e01e44 fix: sasjs/cli and sasjs/core updated to the latest 2023-09-07 12:12:09 +02:00
6f482ec6d9 fix: handsontable v13
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 23s
2023-09-06 21:57:11 +02:00
5e30dc0f89 fix: latest adapter
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 24s
2023-09-06 17:14:49 +02:00
3d76d12c86 chore(release): 6.2.1 [skip ci]
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-08-25)

### Bug Fixes

* approve, history and submit pages grouped in review module ([e056ece](e056ece223))
* updating logic for REPLACE loadtype ([1f2ce55](1f2ce55f24))
2023-08-25 11:46:06 +00:00
93f1b81d70 Merge pull request 'Refactoring solo pages into a modules' (#19) from tsdoc into development
Some checks failed
Release / release (push) Failing after 2m2s
Build / Build-and-ng-test (pull_request) Successful in 24s
Reviewed-on: #19
Reviewed-by: allan <allan@4gl.io>
2023-08-25 11:24:10 +00:00
e2b65ddd82 Merge branch 'development' into tsdoc
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 22s
2023-08-25 11:19:38 +00:00
b64bbe91d4 Merge pull request 'fix: updating logic for REPLACE loadtype' (#25) from replace into development
Reviewed-on: #25
2023-08-25 11:19:16 +00:00
1f2ce55f24 fix: updating logic for REPLACE loadtype
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 24s
Staged rows are always considered as NEW, and previous rows are considered DELETED
This is consistent with the fact that REPLACE involves a delete *, followed by an append.
2023-08-25 12:17:43 +01:00
921157da9e chore(git): Merge branch 'development' into tsdoc
Some checks reported warnings
Build / Build-and-ng-test (pull_request) Successful in 23s
Release / release (push) Has been cancelled
2023-08-24 12:17:01 +02:00
413acf7d05 Merge pull request 'main to dev' (#23) from main into development
Reviewed-on: #23
2023-08-24 10:12:26 +00:00
725f75aa74 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 23s
2023-08-24 11:52:02 +02:00
c64ab8a577 chore(git): Merge branch 'tsdoc' of ssh://git.datacontroller.io:29419/dc/dc into tsdoc
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 22s
2023-08-24 11:50:53 +02:00
1154c99e0a ci: surfer install 2023-08-24 11:44:54 +02:00
5bcdef77b8 Merge branch 'development' into tsdoc
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 22s
2023-08-24 09:43:45 +00:00
7b54fff26e chore: typo fix
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 22s
2023-08-04 12:18:31 +02:00
cd3e0f614b chore: adding comments part 3
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 23s
2023-08-04 12:05:00 +02:00
81c0aec202 chore: removed column.ts leftover 2023-08-04 08:52:53 +02:00
3193bdd720 chore: removing cellValidation leftover 2023-08-03 22:33:16 +02:00
b9a12454e1 chore: removing table.ts leftover 2023-08-03 22:31:59 +02:00
01a857f7c6 chore: adding comments part 2 2023-08-03 22:31:17 +02:00
2bb2eee80e chore: removed commented code about old workaround for excel upload validation 2023-08-03 21:58:50 +02:00
c054ea500d chore: adding comments part1 2023-08-03 17:56:34 +02:00
d7f8201246 ci: tsdoc -> webdoc
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 22s
2023-08-02 09:24:16 +02:00
622cfcc6fe chore: removed edit-route leftover
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 21s
2023-08-01 16:45:18 +02:00
303240e4d2 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 23s
2023-08-01 16:40:03 +02:00
a8b849aede chore: modularization refactor finish 2023-08-01 16:39:45 +02:00
ca281b70c9 chore(git): Merge branch 'development' into tsdoc
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 22s
2023-08-01 14:52:53 +02:00
e056ece223 fix: approve, history and submit pages grouped in review module
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 1m5s
Using compodoc instead of typedoc because of better angular support.
2023-08-01 14:50:04 +02:00
240 changed files with 16196 additions and 31433 deletions

View File

@ -1,5 +1,5 @@
name: Build name: Build
run-name: Running Lint Check run-name: Running Lint Check and Licence checker on Pull Request
on: [pull_request] on: [pull_request]
jobs: jobs:
@ -8,9 +8,16 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 20.14.0
- name: Install Google Chrome
run: |
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list
apt-get update
apt-get install -y google-chrome-stable xvfb
- name: Write .npmrc file - name: Write .npmrc file
run: echo "$NPMRC" > client/.npmrc run: echo "$NPMRC" > client/.npmrc
@ -18,4 +25,27 @@ jobs:
env: env:
NPMRC: ${{ secrets.NPMRC}} NPMRC: ${{ secrets.NPMRC}}
- run: npm run lint:check - name: Lint check
run: npm run lint:check
- name: Install dependencies
run: |
cd client
# Decrypt and Install sheet
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
npm ci
- name: Licence checker
run: |
cd client
npm run license-checker
- name: Angular Tests
run: |
cd client
npm run test:headless
- name: Production Build
run: |
cd client
npm run build

View File

@ -1,223 +0,0 @@
name: Test
run-name: Building and testing development branch
on:
push:
branches:
- development
jobs:
Build-production-and-ng-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Write .npmrc file
run: |
touch client/.npmrc
echo '${{ secrets.NPMRC}}' > client/.npmrc
- name: Install Chrome for Angular tests
run: apt-get update
run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
run: apt install -y ./google-chrome*.deb;
run: export CHROME_BIN=/usr/bin/google-chrome
- name: Write cypress credentials
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
shell: bash
env:
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
- name: Install dependencies
run: npm ci
- name: Check audit
# Audit should fail and stop the CI if critical vulnerability found
run: |
npm audit --audit-level=critical
cd ./sas
npm audit --audit-level=critical
cd ./client
npm audit --audit-level=critical
- name: Angular Tests
run: |
npm test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
- name: Angular Production Build
run: |
npm run postinstall
npm run build
Build-and-test-development:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Write .npmrc file
run: |
touch client/.npmrc
echo '${{ secrets.NPMRC}}' > client/.npmrc
- run: apt-get update
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- run: apt install -y ./google-chrome*.deb;
- run: export CHROME_BIN=/usr/bin/google-chrome
- run: apt-get update -y
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
- run: apt -y install jq
- name: Write cypress credentials
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
shell: bash
env:
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
- name: Install dependencies
run: npm ci
# Install pm2 and prepare SASJS server
- run: npm i -g pm2
- run: curl -L https://github.com/sasjs/server/releases/latest/download/linux.zip > linux.zip
- run: unzip linux.zip
- run: touch .env
- run: echo RUN_TIMES=js >> .env
- run: echo NODE_PATH=node >> .env
- run: echo CORS=enable >> .env
- run: echo WHITELIST=http://localhost:4200 >> .env
- run: cat .env
- run: pm2 start api-linux --wait-ready
- name: Deploy mocked services
run: |
cd ./sas/mocks/sasjs
npm install -g @sasjs/cli
npm install -g replace-in-files-cli
sasjs cbd -t server-ci
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
- name: Install ZIP
run: |
apt-get update
apt-get install zip
- name: Prepare and run frontend and cypress
run: |
cd ./client
mv ./cypress.env.example.json ./cypress.env.json
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
cat ./cypress.env.json
npm run postinstall
# Prepare index.html to SASJS local
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
cat ./cypress.config.ts
# Start frontend and run cypress
npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
- name: Zip Cypress videos
if: always()
run: |
zip -r cypress-videos ./client/cypress/videos
- name: Cypress videos artifacts
uses: actions/upload-artifact@v3
with:
name: cypress-videos.zip
path: cypress-videos.zip
Build-and-test-development-latest-adapter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Write .npmrc file
run: echo "$NPMRC" > client/.npmrc
shell: bash
env:
NPMRC: ${{ secrets.NPMRC}}
- run: apt-get update
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- run: apt install -y ./google-chrome*.deb;
- run: export CHROME_BIN=/usr/bin/google-chrome
- run: apt-get update -y
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
- run: apt -y install jq
- name: Write cypress credentials
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
shell: bash
env:
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
- name: Install dependencies
run: npm ci
# Install pm2 and prepare SASJS server
- run: npm i -g pm2
- run: curl -L https://github.com/sasjs/server/releases/latest/download/linux.zip > linux.zip
- run: unzip linux.zip
- run: touch .env
- run: echo RUN_TIMES=js >> .env
- run: echo NODE_PATH=node >> .env
- run: echo CORS=enable >> .env
- run: echo WHITELIST=http://localhost:4200 >> .env
- run: cat .env
- run: pm2 start api-linux --wait-ready
- name: Deploy mocked services
run: |
cd ./sas/mocks/sasjs
npm install -g @sasjs/cli
npm install -g replace-in-files-cli
sasjs cbd -t server-ci
- name: Install ZIP
run: |
apt-get update
apt-get install zip
- name: Prepare and run frontend and cypress
run: |
cd ./client
mv ./cypress.env.example.json ./cypress.env.json
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
cat ./cypress.env.json
npm run postinstall
npm install @sasjs/adapter@latest
# Prepare index.html to SASJS local
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
cat ./cypress.config.ts
# Start frontend and run cypress
npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
- name: Zip Cypress videos
if: always()
run: |
zip -r cypress-videos ./client/cypress/videos
- name: Cypress videos artifacts
uses: actions/upload-artifact@v3
with:
name: cypress-videos-latest-adapter.zip
path: cypress-videos.zip

View File

@ -1,18 +1,164 @@
name: Release name: Release
run-name: Releasing DC run-name: Testing and Releasing DC
on: on:
push: push:
branches: branches:
- main - main
jobs: jobs:
release: Build-production-and-ng-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 20.14.0
- name: Write .npmrc file
run: |
touch client/.npmrc
echo '${{ secrets.NPMRC}}' > client/.npmrc
- name: Install Chrome for Angular tests
run: |
apt-get update
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
apt install -y ./google-chrome*.deb;
export CHROME_BIN=/usr/bin/google-chrome
- name: Write cypress credentials
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
shell: bash
env:
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
- name: Install dependencies
run: |
cd client
# Decrypt and Install sheet
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
npm ci
- name: Check audit
# Audit should fail and stop the CI if critical vulnerability found
run: |
npm audit --audit-level=critical --omit=dev
cd ./sas
npm audit --audit-level=critical --omit=dev
cd ../client
npm audit --audit-level=critical --omit=dev
- name: Angular Tests
run: |
cd client
npm run test:headless
- name: Angular Production Build
run: |
cd client
npm run postinstall
npm run build
Build-and-test-development:
runs-on: ubuntu-latest
needs: Build-production-and-ng-test
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: 20.14.0
- name: Write .npmrc file
run: |
touch client/.npmrc
echo '${{ secrets.NPMRC}}' > client/.npmrc
- run: apt-get update
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- run: apt install -y ./google-chrome*.deb;
- run: export CHROME_BIN=/usr/bin/google-chrome
- run: apt-get update -y
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
- run: apt -y install jq
- name: Write cypress credentials
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
shell: bash
env:
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
- name: Install dependencies
run: |
cd client
# Decrypt and Install sheet
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
npm ci
# Install pm2 and prepare SASJS server
- run: npm i -g pm2
- run: curl -L https://github.com/sasjs/server/releases/latest/download/linux.zip > linux.zip
- run: unzip linux.zip
- run: touch .env
- run: echo RUN_TIMES=js >> .env
- run: echo NODE_PATH=node >> .env
- run: echo CORS=enable >> .env
- run: echo WHITELIST=http://localhost:4200 >> .env
- run: cat .env
- run: pm2 start api-linux --wait-ready
- name: Deploy mocked services
run: |
cd ./sas/mocks/sasjs
npm install -g @sasjs/cli
npm install -g replace-in-files-cli
sasjs cbd -t server-ci
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
- name: Install ZIP
run: |
apt-get update
apt-get install zip
- name: Prepare and run frontend and cypress
run: |
cd ./client
mv ./cypress.env.example.json ./cypress.env.json
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
cat ./cypress.env.json
npm run postinstall
# Prepare index.html to SASJS local
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
cat ./cypress.config.ts
# Start frontend and run cypress
npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
- name: Zip Cypress videos
if: always()
run: |
zip -r cypress-videos ./client/cypress/videos
- name: Add cypress videos artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: cypress-videos.zip
path: cypress-videos.zip
release:
runs-on: ubuntu-latest
needs: [Build-production-and-ng-test, Build-and-test-development]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: 20.14.0
- name: Write .npmrc file - name: Write .npmrc file
run: | run: |
@ -30,25 +176,39 @@ jobs:
npm i -g @sasjs/cli npm i -g @sasjs/cli
# jq is used to parse the release JSON # jq is used to parse the release JSON
apt-get install jq -y apt-get install jq -y
# doxygen is used for the SASJS docs
apt-get update
apt-get install doxygen -y
- name: Frontend Preliminary Build
description: We want to prevent creating empty release if frontend fails
run: |
cd client
# Decrypt and Install sheet
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
npm ci
npm i webpack
npm run build
- name: Create Empty Release (assets are posted later) - name: Create Empty Release (assets are posted later)
run: | run: |
npm i npm i
npm i -g semantic-release npm i -g semantic-release
# We do a semantic-release DRY RUN to make the job fail if there are no changes to release
GITEA_TOKEN=${{ secrets.RELEASE_TOKEN }} GITEA_URL=https://git.datacontroller.io semantic-release --dry-run | grep -q "There are no relevant changes, so no new version is released." && exit 1
GITEA_TOKEN=${{ secrets.RELEASE_TOKEN }} GITEA_URL=https://git.datacontroller.io semantic-release GITEA_TOKEN=${{ secrets.RELEASE_TOKEN }} GITEA_URL=https://git.datacontroller.io semantic-release
- name: Frontend Build - name: Frontend Build
description: Must be created AFTER the release as the version (git tag) is used in the interface description: Must be created AFTER the release as the version (git tag) is used in the interface
run: | run: |
cd client cd client
npm ci
npm run build npm run build
- name: Build SAS9 EBI Release - name: Build SAS9 EBI Release
description: Compile SAS 9 services, remove tests & create deployment program description: Compile SAS 9 services, remove tests & create deployment program
run: | run: |
cd sas cd sas
npm ci npm i
sasjs c -t sas9 sasjs c -t sas9
rm -rf sasjsbuild/tests rm -rf sasjsbuild/tests
sasjs b -t sas9 sasjs b -t sas9
@ -85,6 +245,7 @@ jobs:
rm sasjsbuild/services/clickme.html rm sasjsbuild/services/clickme.html
sasjs b -t viya sasjs b -t viya
cp sasjsbuild/viya.sas ./viya.sas cp sasjsbuild/viya.sas ./viya.sas
cp sasjsbuild/viya.json ./viya.json
- name: Zip Frontend (including viya.json for full viya deploy) - name: Zip Frontend (including viya.json for full viya deploy)
run: | run: |
@ -97,15 +258,21 @@ jobs:
run: | run: |
cd client cd client
npm -g install cloudron-surfer npm -g install cloudron-surfer
npm run typedoc npm run compodoc:build
surfer put --token ${{ secrets.TSDOC_TOKEN }} --server tsdoc.datacontroller.io ../tsdoc / surfer put --token ${{ secrets.TSDOC_TOKEN }} --server webdoc.datacontroller.io documentation/* /
- name: Release code.datacontroller.io
run: |
cd sas
sasjs doc
surfer put --token ${{ secrets.CODE_DATACONTROLLER_IO }} --server code.datacontroller.io sasjsbuild/sasdocs/* /
- name: Upload assets to release - name: Upload assets to release
run: | run: |
RELEASE_ID=`curl -k 'https://git.datacontroller.io/api/v1/repos/dc/dc/releases/latest?access_token=${{ secrets.RELEASE_TOKEN }}' | jq -r '.id'` RELEASE_ID=`curl -k 'https://git.datacontroller.io/api/v1/repos/dc/dc/releases/latest?access_token=${{ secrets.RELEASE_TOKEN }}' | jq -r '.id'`
RELEASE_BODY=`curl -k 'https://git.datacontroller.io/api/v1/repos/dc/dc/releases/latest?access_token=${{ secrets.RELEASE_TOKEN }}' | jq -r '.body'` RELEASE_BODY=`curl -k 'https://git.datacontroller.io/api/v1/repos/dc/dc/releases/latest?access_token=${{ secrets.RELEASE_TOKEN }}' | jq -r '.body'`
# Update body # Update body
curl --data '{"draft": true,"body":"'"$RELEASE_BODY\n\nFor installation instructions, please visit https://docs.datacontroller.io/"'"}' -X PATCH --header 'Content-Type: application/json' -k https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID?access_token=${{ secrets.RELEASE_TOKEN }} curl --data '{"draft": false,"body":"'"$RELEASE_BODY\n\nFor installation instructions, please visit https://docs.datacontroller.io/"'"}' -X PATCH --header 'Content-Type: application/json' -k https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID?access_token=${{ secrets.RELEASE_TOKEN }}
# Upload assets # Upload assets
URL="https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID/assets?access_token=${{ secrets.RELEASE_TOKEN }}" URL="https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID/assets?access_token=${{ secrets.RELEASE_TOKEN }}"
curl -k $URL -F attachment=@frontend.zip curl -k $URL -F attachment=@frontend.zip
@ -114,3 +281,4 @@ jobs:
curl -k $URL -F attachment=@sas/sasjs_server.json.zip curl -k $URL -F attachment=@sas/sasjs_server.json.zip
curl -k $URL -F attachment=@sas/sas9.sas curl -k $URL -F attachment=@sas/sas9.sas
curl -k $URL -F attachment=@sas/viya.sas curl -k $URL -F attachment=@sas/viya.sas
curl -k $URL -F attachment=@sas/viya.json

4
.gitignore vendored
View File

@ -10,6 +10,10 @@ client/src/environments/version.ts
client/cypress/screenshots client/cypress/screenshots
client/cypress/results client/cypress/results
client/cypress/videos client/cypress/videos
client/documentation
client/**/sheet-crypto.tgz
client/.nx
client/libraries/sheet-crypto.tgz
cypress.env.json cypress.env.json
sasjsbuild sasjsbuild
sasjsresults sasjsresults

2
.npmrc
View File

@ -1 +1 @@
legacy-peer-deps=false legacy-peer-deps=true

View File

@ -6,11 +6,13 @@
"@semantic-release/commit-analyzer", "@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator", "@semantic-release/release-notes-generator",
"@semantic-release/changelog", "@semantic-release/changelog",
"@semantic-release/npm",
[ [
"@semantic-release/git", "@semantic-release/git",
{ {
"assets": [ "assets": [
"CHANGELOG.md" "CHANGELOG.md",
"package.json"
] ]
} }
], ],

35
.vscode/settings.json vendored
View File

@ -1,18 +1,19 @@
{ {
"cSpell.words": [ "cSpell.words": [
"SYSERRORTEXT", "Licence",
"SYSWARNINGTEXT" "SYSERRORTEXT",
], "SYSWARNINGTEXT",
"editor.rulers": [ "xlmaprules",
80 "xlmaps"
], ],
"files.trimTrailingWhitespace": true, "editor.rulers": [80],
"[markdown]": { "files.trimTrailingWhitespace": true,
"files.trimTrailingWhitespace": false "[markdown]": {
}, "files.trimTrailingWhitespace": false
"workbench.colorCustomizations": { },
"titleBar.activeForeground": "#ebe8e8", "workbench.colorCustomizations": {
"titleBar.activeBackground": "#95ff0053", "titleBar.activeForeground": "#ebe8e8",
}, "titleBar.activeBackground": "#95ff0053"
"terminal.integrated.wordSeparators": " ()[]{}',\"`─‘’" },
} "terminal.integrated.wordSeparators": " ()[]{}',\"`─‘’"
}

View File

@ -1,14 +1,280 @@
# [6.2.0](https://git.datacontroller.io/dc/dc/compare/v6.1.0...v6.2.0) (2023-08-24) ## [6.10.1](https://git.datacontroller.io/dc/dc/compare/v6.10.0...v6.10.1) (2024-06-07)
### Bug Fixes ### Bug Fixes
* re-enabling full REPLACE uploads ([08e39c4](https://git.datacontroller.io/dc/dc/commit/08e39c4fca570406f9aad3d907cb04596421d074)) * adding 60 more colours to crayons table. Closes [#112](https://git.datacontroller.io/dc/dc/issues/112) ([3521579](https://git.datacontroller.io/dc/dc/commit/3521579dead089eebf62455686be3aee88bde687))
* terms and conditions colours, editor on smaller screens show only icons ([e32d44b](https://git.datacontroller.io/dc/dc/commit/e32d44b1bcdfeea43d19b21ec0ddf4af1ce3992a))
# [6.10.0](https://git.datacontroller.io/dc/dc/compare/v6.9.0...v6.10.0) (2024-06-07)
### Features ### Features
* support for European numeric formats ([e48e47b](https://git.datacontroller.io/dc/dc/commit/e48e47bc635452b59e107b235e597c26e748875e)) * updated handsontable to v14 ([2f8d0b7](https://git.datacontroller.io/dc/dc/commit/2f8d0b764a957ad8c11cd1088fad5e0670aa1731))
# [6.9.0](https://git.datacontroller.io/dc/dc/compare/v6.8.5...v6.9.0) (2024-05-31)
### Bug Fixes
* added colors.scss file, start of a refactor ([110ad9a](https://git.datacontroller.io/dc/dc/commit/110ad9a6e9ed39bd5591ae65c2d0005ba47ca758))
* added stealFocus directive ([9a79f37](https://git.datacontroller.io/dc/dc/commit/9a79f37bf143a1e05df7407358e2687c678e3e68))
### Features
* added app settings service to handle theme persistance, fix: optimised dark mode contrast ([35844e0](https://git.datacontroller.io/dc/dc/commit/35844e0cf1a639553269f2ab0f8666a56ab5cc47))
* **dark mode:** clarity optimizations ([afa7e38](https://git.datacontroller.io/dc/dc/commit/afa7e380aa3bdabd380c038522b9d73d9a8a3b91))
* **dark mode:** lineage and metadata ([27907ed](https://git.datacontroller.io/dc/dc/commit/27907ed00fe81f4c752ffe99d2fb029d5c884f0a))
* **dark mode:** refactoring clarity to enable dark mode, added toggle button ([5564aea](https://git.datacontroller.io/dc/dc/commit/5564aea9c25f8e81ff85afa8352325b9992e4043))
* **dark mode:** removing custom css rules so clarity can handle dark/light modes. Handsontable css for dark mode ([2c0afd0](https://git.datacontroller.io/dc/dc/commit/2c0afd02684cdf3bda374731b0359665e00ed95d))
## [6.8.5](https://git.datacontroller.io/dc/dc/compare/v6.8.4...v6.8.5) (2024-05-23)
### Bug Fixes
* bitemporal load issue [#105](https://git.datacontroller.io/dc/dc/issues/105) ([967698e](https://git.datacontroller.io/dc/dc/commit/967698e4ce1e0abcbc6f0aff8a4be6c512dee93c))
## [6.8.4](https://git.datacontroller.io/dc/dc/compare/v6.8.3...v6.8.4) (2024-05-22)
### Bug Fixes
* new approach to fixing [#105](https://git.datacontroller.io/dc/dc/issues/105) ([c11bd9a](https://git.datacontroller.io/dc/dc/commit/c11bd9a2c55e49f10451962cb2e222c21206bce5))
## [6.8.3](https://git.datacontroller.io/dc/dc/compare/v6.8.2...v6.8.3) (2024-05-09)
### Bug Fixes
* updating core to increase filename length, closes [#103](https://git.datacontroller.io/dc/dc/issues/103) ([ee58fd5](https://git.datacontroller.io/dc/dc/commit/ee58fd5b4bc0dd3e3f232c4f26bb85b2e7fe2b54))
## [6.8.2](https://git.datacontroller.io/dc/dc/compare/v6.8.1...v6.8.2) (2024-05-03)
### Bug Fixes
* dc_request_logs option feature ([93758ef](https://git.datacontroller.io/dc/dc/commit/93758efb275966c181f1ee8b6c752010909a0282))
* release process ([c0dc919](https://git.datacontroller.io/dc/dc/commit/c0dc9191e3b95ea6f7e5021fc0bdbcab0af4cc64))
## [6.8.1](https://git.datacontroller.io/dc/dc/compare/v6.8.0...v6.8.1) (2024-05-02)
### Bug Fixes
* hide approve button when table revertable ([ec0f539](https://git.datacontroller.io/dc/dc/commit/ec0f539a337b176c83a661ff520a6892d47efa02))
# [6.8.0](https://git.datacontroller.io/dc/dc/compare/v6.7.0...v6.8.0) (2024-05-02)
### Bug Fixes
* ci sheet lib, submit message auto focus ([c5e4650](https://git.datacontroller.io/dc/dc/commit/c5e46503272f3f3d9cd83ac04225babf79d4de44))
* **clarity:** new version style issues ([8c7de5a](https://git.datacontroller.io/dc/dc/commit/8c7de5aad7e7e32a64769696af9b93eb9a6225d3))
* cypress tests ([3dd85cc](https://git.datacontroller.io/dc/dc/commit/3dd85cc60bd5ac99bc930b6b9c89a8e707e4d51d))
* ensuring that only restorable versions are restorable ([a402856](https://git.datacontroller.io/dc/dc/commit/a4028562ce91b32ff971ab9821328b97cd23f381))
* ensuring version history only includes loaded versions ([51ebd25](https://git.datacontroller.io/dc/dc/commit/51ebd25aa362aa8e66c83b29b2c64aa0f206f5bd))
* final testing on restore feature ([297a84d](https://git.datacontroller.io/dc/dc/commit/297a84d3a4ebb47bef7f3ca9758978d727afed8d))
* issue with multiple adds/deletes, [#84](https://git.datacontroller.io/dc/dc/issues/84) ([904ca30](https://git.datacontroller.io/dc/dc/commit/904ca30f918da085fa05dae066367b512933d1a9))
* load_ref var ([aaad9f7](https://git.datacontroller.io/dc/dc/commit/aaad9f7207115599a006980fff099d59738dd2cd))
* removing alerts dummy data, closes [#93](https://git.datacontroller.io/dc/dc/issues/93) ([eba21e9](https://git.datacontroller.io/dc/dc/commit/eba21e96b4fa34e63b4477281f47d9a01d621f2e))
* restore table version improvement ([549f357](https://git.datacontroller.io/dc/dc/commit/549f35766ba7b5bbe55694845e85bfefc4193375))
* **sas:** viewer versions fix ([c6595c1](https://git.datacontroller.io/dc/dc/commit/c6595c1f618803d9202cba1a1fe76986449cf2e2))
* stage and approve buttons renaming ([ef81e33](https://git.datacontroller.io/dc/dc/commit/ef81e33f704d0b4f99405d96498e1d29ac817982))
* supporting SCD2 data reversions ([fa8396f](https://git.datacontroller.io/dc/dc/commit/fa8396f0394cbddb6dbacb4b355de078fad49980))
* table info modal, versions - column names ([801c8c6](https://git.datacontroller.io/dc/dc/commit/801c8c6a9fb95388a06a6c6284fec4dc25bb77c5))
* **updates:** angular, clarity, resolved legacy-peer-deps ([c60dd65](https://git.datacontroller.io/dc/dc/commit/c60dd65a1637333f11a0c39ef697c7292a6ede07))
### Features
* backend to show in getchangeinfo whether a user is allowed to restore ([8769841](https://git.datacontroller.io/dc/dc/commit/8769841f08694f672ef7ae1a17beacd0dbedda52))
* list versions of target tables (backend) ([f8a14d4](https://git.datacontroller.io/dc/dc/commit/f8a14d4bdef055b99930491d1f6fabe55a50a497))
* restore ([604c2e7](https://git.datacontroller.io/dc/dc/commit/604c2e70bdeeeb1aa5bb18b94f525ebd049397fa))
* SAS services & tests for RESTORE, [#84](https://git.datacontroller.io/dc/dc/issues/84) ([9ad7ae4](https://git.datacontroller.io/dc/dc/commit/9ad7ae47b5e793ce68ab21c9eeb8dee6cb85e496))
* staging page, restore buttons ([02a8a1c](https://git.datacontroller.io/dc/dc/commit/02a8a1c5654350cafc53b749cceb686fc6848c33))
* table metadata modal, versions tab (and link) ([b27fea5](https://git.datacontroller.io/dc/dc/commit/b27fea5b91e33b4673a3a991aedae558e366ca29))
* **versions:** getting list of versions (plus test) ([8003da9](https://git.datacontroller.io/dc/dc/commit/8003da94e615463ed3ddfd60b0cbf2e58615eab1))
# [6.7.0](https://git.datacontroller.io/dc/dc/compare/v6.6.4...v6.7.0) (2024-04-01)
### Features
* numeric values in hot dropdown aligned right ([9635626](https://git.datacontroller.io/dc/dc/commit/963562621ddf0e8d24a29a8481c5e6da1b040708))
## [6.6.4](https://git.datacontroller.io/dc/dc/compare/v6.6.3...v6.6.4) (2024-04-01)
### Bug Fixes
* ordering SOFTSELECT numerically in dropdown ([f522038](https://git.datacontroller.io/dc/dc/commit/f522038b8ddb1da14b8adbf8346d0a4539a94cc8)), closes [#85](https://git.datacontroller.io/dc/dc/issues/85)
* reverting col ([fbbcf90](https://git.datacontroller.io/dc/dc/commit/fbbcf90956bf538b032b0107c07b8576d20353b9))
* typo ([31d4e5c](https://git.datacontroller.io/dc/dc/commit/31d4e5c727f790d428fb2ea8da60dca929561805))
## [6.6.3](https://git.datacontroller.io/dc/dc/compare/v6.6.2...v6.6.3) (2024-02-26)
### Bug Fixes
* allow empty clause value when NE or CONTAINS ([432450a](https://git.datacontroller.io/dc/dc/commit/432450a15b51a269821ba1d430854f5d1dd04703))
## [6.6.2](https://git.datacontroller.io/dc/dc/compare/v6.6.1...v6.6.2) (2024-02-22)
### Bug Fixes
* excel with commas getting wrapped in quotes ([3860134](https://git.datacontroller.io/dc/dc/commit/38601346a529cfe3787bb286a639e0293c365020))
## [6.6.1](https://git.datacontroller.io/dc/dc/compare/v6.6.0...v6.6.1) (2024-02-19)
### Bug Fixes
* **client:** bumped @sasjs/adapter with fixed redirected login ([eb1c09d](https://git.datacontroller.io/dc/dc/commit/eb1c09d7909ba07faf763da261545dc1efaec1b3))
# [6.6.0](https://git.datacontroller.io/dc/dc/compare/v6.5.2...v6.6.0) (2024-02-12)
### Bug Fixes
* adjust the col numbers in extracted data ([cff5989](https://git.datacontroller.io/dc/dc/commit/cff598955930d2581349e5c6e8b2dd3f9ac96b4c))
### Features
* extra table metadata for [#75](https://git.datacontroller.io/dc/dc/issues/75) ([837821f](https://git.datacontroller.io/dc/dc/commit/837821fd01477d340524dfdaf8dd3d3758cf3095))
* show dsnote on hover title ([6565834](https://git.datacontroller.io/dc/dc/commit/6565834ad4089ecf2de39967e6ed6f217ee4a0a5))
## [6.5.2](https://git.datacontroller.io/dc/dc/compare/v6.5.1...v6.5.2) (2024-02-06)
### Bug Fixes
* ordering mpe_selectbox data by the data values after selectbox_order ([2b54034](https://git.datacontroller.io/dc/dc/commit/2b5403497317632a4be8a00f21455c036f1e6461))
## [6.5.1](https://git.datacontroller.io/dc/dc/compare/v6.5.0...v6.5.1) (2024-02-02)
### Bug Fixes
* ensuring submitter email can be pulled from mpe_emails ([eac0104](https://git.datacontroller.io/dc/dc/commit/eac0104d7aebaf98ff1d1c504c1ce3b25d4a0ce8))
# [6.5.0](https://git.datacontroller.io/dc/dc/compare/v6.4.0...v6.5.0) (2024-01-26)
### Features
* filtering by reference to Variables as well as Values ([6eb1aa8](https://git.datacontroller.io/dc/dc/commit/6eb1aa85d29294d63e6af377e622fbed7fd1fab8))
# [6.4.0](https://git.datacontroller.io/dc/dc/compare/v6.3.1...v6.4.0) (2024-01-24)
### Bug Fixes
* add dcLib to globals ([5d93346](https://git.datacontroller.io/dc/dc/commit/5d93346b52eda27c2829770e96686a713296d373))
* add service to get xlmap rules and fixed interface name ([9ffa30a](https://git.datacontroller.io/dc/dc/commit/9ffa30ab747f5b62acbd452431a5e6e440afcb80))
* increasing length of mpe_excel_map cols to ([2d4d068](https://git.datacontroller.io/dc/dc/commit/2d4d068413dcdac98581f08939e74bde65b73428))
* providing info on mapids to FE ([fd94945](https://git.datacontroller.io/dc/dc/commit/fd94945466c1a797ddc89815258a65624a9cb0cf))
* removing tables from EDIT menu that are in xlmaps ([9550ae4](https://git.datacontroller.io/dc/dc/commit/9550ae4d1154a0272f8a2427ac9d2afdfd699c96))
* removing XLMAP_TARGETLIBDS from mpe_xlmaps_rules table ([93702c6](https://git.datacontroller.io/dc/dc/commit/93702c63dc280cdba1e46f0fd8fe0deaec879611))
* renaming TABLE macvar to LOAD_REF in postdata.sas ([01915a2](https://git.datacontroller.io/dc/dc/commit/01915a2db9a4dfb94e4e8213e2c32181da36d349))
* reverting xlmap in getdata change ([2d6e747](https://git.datacontroller.io/dc/dc/commit/2d6e747db9b84e9fb0dfcf9102a2f7dd2cb51891))
* update edit tab to load ([516e5a2](https://git.datacontroller.io/dc/dc/commit/516e5a206216f79ab1dce9f4eab0d31115743160))
### Features
* adding ability to define the target table for excel maps ([c86fba9](https://git.datacontroller.io/dc/dc/commit/c86fba9dc75ddc6033132f469ad1c31b9131b12e))
* adding ismap attribute to getdata response (and fixing test) ([2702bb3](https://git.datacontroller.io/dc/dc/commit/2702bb3c84c45903def1aa2b8cc20a6dd080281b))
* Complex Excel Uploads ([cf19381](https://git.datacontroller.io/dc/dc/commit/cf193810606f287b8d6f864c4eb64d43c5ab5f3c)), closes [#69](https://git.datacontroller.io/dc/dc/issues/69)
* Create Tables / Files dropdown under load tab ([b473b19](https://git.datacontroller.io/dc/dc/commit/b473b198a61f468dff74cd8e64692e7847084a80))
* display list of maps in sidebar ([5aec024](https://git.datacontroller.io/dc/dc/commit/5aec0242429942f8a989b5fb79f8d3865e9de01a))
* implemented the logic for xlmap component ([50696bb](https://git.datacontroller.io/dc/dc/commit/50696bb926dd00472db65a008771a4b6352871be))
* model changes for [#69](https://git.datacontroller.io/dc/dc/issues/69) ([271543a](https://git.datacontroller.io/dc/dc/commit/271543a446a2116718f99f0540e3cd911f9f5fe7))
* new getxlmaps service to return rules for a particular xlmap_id ([56264ec](https://git.datacontroller.io/dc/dc/commit/56264ecc6908bf6c8e3e666dfeba7068d6195df8))
* validating the excel map after stage (adding load-ref) ([a485c3b](https://git.datacontroller.io/dc/dc/commit/a485c3b78724a36f7bacb264fb02140cc62d6512))
## [6.3.1](https://git.datacontroller.io/dc/dc/compare/v6.3.0...v6.3.1) (2024-01-01)
### Bug Fixes
* enabling excel uploads to tables with retained keys, also adding more validation to MPE_TABLES updates ([3efccc4](https://git.datacontroller.io/dc/dc/commit/3efccc4cf3752763d049836724f2491c287f65db))
# [6.3.0](https://git.datacontroller.io/dc/dc/compare/v6.2.8...v6.3.0) (2023-12-04)
### Features
* viewer row handle ([dadac4f](https://git.datacontroller.io/dc/dc/commit/dadac4f13f85b5446198b6340cad28844defc94d))
## [6.2.8](https://git.datacontroller.io/dc/dc/compare/v6.2.7...v6.2.8) (2023-12-04)
### Bug Fixes
* bumping sasjs/core to fix mp_loadformat issue ([a1d308e](https://git.datacontroller.io/dc/dc/commit/a1d308ea078786b27bf7ec940d018fc657d4c398))
* new logic for -fc suffix. Closes [#63](https://git.datacontroller.io/dc/dc/issues/63) ([5579db0](https://git.datacontroller.io/dc/dc/commit/5579db0eafc668b1bc310099b7cc3062e0598fc4))
## [6.2.7](https://git.datacontroller.io/dc/dc/compare/v6.2.6...v6.2.7) (2023-11-09)
### Bug Fixes
* **audit:** updated crypto-js (hashing rows in dynamic cell validation) ([a7aa42a](https://git.datacontroller.io/dc/dc/commit/a7aa42a59b71597399924b8d2d06010c806321f3))
* missing dependency and avoiding label length limit issue ([91f128c](https://git.datacontroller.io/dc/dc/commit/91f128c2fead1e4f72267d689e67f49ec9a2ab35))
## [6.2.6](https://git.datacontroller.io/dc/dc/compare/v6.2.5...v6.2.6) (2023-10-18)
### Bug Fixes
* bumping core to address mm_assigndirectlib issue ([c27cdab](https://git.datacontroller.io/dc/dc/commit/c27cdab3fccbde814a29424d0344173a73ea816c))
## [6.2.5](https://git.datacontroller.io/dc/dc/compare/v6.2.4...v6.2.5) (2023-10-17)
### Bug Fixes
* enabling AUTHDOMAIN in MM_ASSIGNDIRECTLIB ([008b45a](https://git.datacontroller.io/dc/dc/commit/008b45ad175ec0e6026f5ef3bc210470226e328f))
## [6.2.4](https://git.datacontroller.io/dc/dc/compare/v6.2.3...v6.2.4) (2023-10-16)
### Bug Fixes
* Enable display of metadata-only tables. Closes [#56](https://git.datacontroller.io/dc/dc/issues/56) ([f3e82b4](https://git.datacontroller.io/dc/dc/commit/f3e82b4ee2a9c1c851f812ac60e9eaf05f91a0f9))
## [6.2.3](https://git.datacontroller.io/dc/dc/compare/v6.2.2...v6.2.3) (2023-10-12)
### Bug Fixes
* bumping core library to avoid non-ascii char in mp_validatecols.sas. [#50](https://git.datacontroller.io/dc/dc/issues/50) ([11b06f6](https://git.datacontroller.io/dc/dc/commit/11b06f6416300b6d70b1570c415d5a5c004976db))
* removing copyright symbol from mpe_alerts macro. [#50](https://git.datacontroller.io/dc/dc/issues/50) ([adb7eb7](https://git.datacontroller.io/dc/dc/commit/adb7eb77550c68a2dab15a6ff358129820e9b612))
## [6.2.2](https://git.datacontroller.io/dc/dc/compare/v6.2.1...v6.2.2) (2023-10-09)
### Bug Fixes
* updated SheetJS (crypto) to the latest ([8bd0dd2](https://git.datacontroller.io/dc/dc/commit/8bd0dd22c258911672303869e4df893a98e93575))
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-09)
### Bug Fixes
* approve, history and submit pages grouped in review module ([e056ece](https://git.datacontroller.io/dc/dc/commit/e056ece2234ef6aab050f6a5b1f8de633b163d91))
* closes [#39](https://git.datacontroller.io/dc/dc/issues/39) upcase issue in MPE_SECURITY ([a00d31c](https://git.datacontroller.io/dc/dc/commit/a00d31caf3c5634cd61a4700fb175e76856edbb6))
* handsontable v13 ([6f482ec](https://git.datacontroller.io/dc/dc/commit/6f482ec6d909907a304ef9975262889e2370035f))
* latest adapter ([5e30dc0](https://git.datacontroller.io/dc/dc/commit/5e30dc0f892fab2af41f4ea56e30f27ec3b3912e))
* sasjs/cli and sasjs/core updated to the latest ([8571e01](https://git.datacontroller.io/dc/dc/commit/8571e01e44a8cb6df9d150d271c34bb75bffdf31))
* updating editors/stagedata to address issues in particular viya configurations as described in issue [#33](https://git.datacontroller.io/dc/dc/issues/33) ([94ab949](https://git.datacontroller.io/dc/dc/commit/94ab949df8c75072525751a2156b7a32c2e641dc))
* updating logic for REPLACE loadtype ([1f2ce55](https://git.datacontroller.io/dc/dc/commit/1f2ce55f249f4af56f0cacdec47e69246cd47431))
# [6.2.0](https://git.datacontroller.io/dc/dc/compare/v6.1.0...v6.2.0) (2023-08-24) # [6.2.0](https://git.datacontroller.io/dc/dc/compare/v6.1.0...v6.2.0) (2023-08-24)
@ -17,7 +283,6 @@
* re-enabling full REPLACE uploads ([08e39c4](https://git.datacontroller.io/dc/dc/commit/08e39c4fca570406f9aad3d907cb04596421d074)) * re-enabling full REPLACE uploads ([08e39c4](https://git.datacontroller.io/dc/dc/commit/08e39c4fca570406f9aad3d907cb04596421d074))
### Features ### Features
* support for European numeric formats ([e48e47b](https://git.datacontroller.io/dc/dc/commit/e48e47bc635452b59e107b235e597c26e748875e)) * support for European numeric formats ([e48e47b](https://git.datacontroller.io/dc/dc/commit/e48e47bc635452b59e107b235e597c26e748875e))

View File

@ -53,6 +53,17 @@ npm run lint:fix
Typedoc is used for generating typescript documentation based on the code. Typedoc is used for generating typescript documentation based on the code.
That part is automated and beign done as a part of CI job. That part is automated and beign done as a part of CI job.
# Release
Release is automated as a part of CI job. Workflow file: `.gitea/workflows/release.yaml`.
It will run automatically when branch merged to the `main` branch.
IMPORTANT!
If release job fails, after it has been created empty release and a tag, we must not re-run the relase job until we removed the newly create GIT TAG and RELEASE.
To remove the git tag run:
```
git push -d origin vX.X.X
```
To remove the release, you need to do it with repo administration over at [https://git.datacontroller.io/dc/dc](https://git.datacontroller.io/dc/dc)
# Troubleshooting # Troubleshooting
## Makedata service "could not create directory" error ## Makedata service "could not create directory" error

View File

@ -27,4 +27,6 @@ For more information:
* Main site: https://datacontroller.io * Main site: https://datacontroller.io
* Docs: https://docs.datacontroller.io * Docs: https://docs.datacontroller.io
* Code: https://code.datacontroller.io * Code: https://code.datacontroller.io
For support, contact support@4gl.io or reach out on [Matrix](https://matrix.to/#/#dc:4gl.io)!

View File

@ -45,6 +45,7 @@
"numbro", "numbro",
"@clr/icons", "@clr/icons",
"@sasjs/adapter", "@sasjs/adapter",
"@sasjs/utils/types/serverType",
"@sasjs/utils/input/validators", "@sasjs/utils/input/validators",
"@sasjs/utils/utils/bytesToSize", "@sasjs/utils/utils/bytesToSize",
"base64-arraybuffer", "base64-arraybuffer",
@ -67,7 +68,6 @@
"src/styles.scss" "src/styles.scss"
], ],
"scripts": [ "scripts": [
"node_modules/@clr/icons/clr-icons.min.js",
"node_modules/marked/marked.min.js" "node_modules/marked/marked.min.js"
] ]
}, },
@ -116,10 +116,10 @@
"builder": "@angular-devkit/build-angular:dev-server", "builder": "@angular-devkit/build-angular:dev-server",
"configurations": { "configurations": {
"production": { "production": {
"browserTarget": "datacontroller:build:production" "buildTarget": "datacontroller:build:production"
}, },
"development": { "development": {
"browserTarget": "datacontroller:build:development" "buildTarget": "datacontroller:build:development"
} }
}, },
"defaultConfiguration": "development" "defaultConfiguration": "development"
@ -127,30 +127,27 @@
"extract-i18n": { "extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n", "builder": "@angular-devkit/build-angular:extract-i18n",
"options": { "options": {
"browserTarget": "datacontroller:build" "buildTarget": "datacontroller:build"
} }
}, },
"test": { "test": {
"builder": "@angular-devkit/build-angular:karma", "builder": "@angular-devkit/build-angular:karma",
"options": { "options": {
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"codeCoverage": true,
"polyfills": [ "polyfills": [
"src/polyfills.ts", "src/polyfills.ts",
"zone.js", "zone.js",
"zone.js/testing" "zone.js/testing"
], ],
"styles": [ "tsConfig": "tsconfig.spec.json",
"src/styles.scss" "inlineStyleLanguage": "scss",
],
"scripts": [
],
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
"src/assets" "src/assets"
], ],
"styles": [
"src/styles.scss"
],
"scripts": [],
"karmaConfig": "karma.conf.js" "karmaConfig": "karma.conf.js"
} }
}, },

View File

@ -9,6 +9,8 @@ export default defineConfig({
html: true, html: true,
json: false, json: false,
}, },
viewportHeight: 900,
viewportWidth: 1600,
chromeWebSecurity: false, chromeWebSecurity: false,
defaultCommandTimeout: 30000, defaultCommandTimeout: 30000,

View File

@ -221,13 +221,13 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (
approvalButton.innerText approvalButton.innerText
.toLowerCase() .toLowerCase()
.includes('go to approvals screen') .includes('approve')
) { ) {
approvalButton.click() approvalButton.click()
break break

View File

@ -405,13 +405,13 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (
approvalButton.innerText approvalButton.innerText
.toLowerCase() .toLowerCase()
.includes('go to approvals screen') .includes('approve')
) { ) {
approvalButton.click() approvalButton.click()
break break
@ -438,13 +438,13 @@ const rejectExcel = (callback?: any) => {
const acceptExcel = (callback?: any) => { const acceptExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (
approvalButton.innerText approvalButton.innerText
.toLowerCase() .toLowerCase()
.includes('go to approvals screen') .includes('approve')
) { ) {
approvalButton.click() approvalButton.click()
break break

View File

@ -159,20 +159,21 @@ context('filtering tests: ', function () {
}) })
}) })
it('7 | filter bestnum field BETWEEN', (done) => { // TODO: fix
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test') // it('7 | filter bestnum field BETWEEN', (done) => {
// openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
openFilterPopup(() => { // openFilterPopup(() => {
setFilterWithValue('SOME_BESTNUM', '0-10', 'between', () => { // setFilterWithValue('SOME_BESTNUM', '0-10', 'between', () => {
checkInfoBarIncludes( // checkInfoBarIncludes(
`AND,AND,0,SOME_BESTNUM,BETWEEN,0 AND 10`, // `AND,AND,0,SOME_BESTNUM,BETWEEN,0 AND 10`,
(includes: boolean) => { // (includes: boolean) => {
if (includes) done() // if (includes) done()
} // }
) // )
}) // })
}) // })
}) // })
this.afterEach(() => { this.afterEach(() => {
// cy.visit(`${hostUrl}/SASLogon/logout`) // cy.visit(`${hostUrl}/SASLogon/logout`)

View File

@ -699,13 +699,13 @@ const submitTable = (callback?: any) => {
const approveTable = (callback?: any) => { const approveTable = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (
approvalButton.innerText approvalButton.innerText
.toLowerCase() .toLowerCase()
.includes('go to approvals screen') .includes('approve')
) { ) {
approvalButton.click() approvalButton.click()
break break

View File

@ -125,13 +125,13 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (
approvalButton.innerText approvalButton.innerText
.toLowerCase() .toLowerCase()
.includes('go to approvals screen') .includes('approve')
) { ) {
approvalButton.click() approvalButton.click()
break break

View File

@ -221,14 +221,10 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (approvalButton.innerText.toLowerCase().includes('approve')) {
approvalButton.innerText
.toLowerCase()
.includes('go to approvals screen')
) {
approvalButton.click() approvalButton.click()
break break
} }

View File

@ -407,14 +407,10 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (approvalButton.innerText.toLowerCase().includes('approve')) {
approvalButton.innerText
.toLowerCase()
.includes('go to approvals screen')
) {
approvalButton.click() approvalButton.click()
break break
} }
@ -440,14 +436,10 @@ const rejectExcel = (callback?: any) => {
const acceptExcel = (callback?: any) => { const acceptExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (approvalButton.innerText.toLowerCase().includes('approve')) {
approvalButton.innerText
.toLowerCase()
.includes('go to approvals screen')
) {
approvalButton.click() approvalButton.click()
break break
} }

View File

@ -699,14 +699,10 @@ const submitTable = (callback?: any) => {
const approveTable = (callback?: any) => { const approveTable = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (approvalButton.innerText.toLowerCase().includes('approve')) {
approvalButton.innerText
.toLowerCase()
.includes('go to approvals screen')
) {
approvalButton.click() approvalButton.click()
break break
} }

View File

@ -125,14 +125,10 @@ const submitExcel = (callback?: any) => {
const rejectExcel = (callback?: any) => { const rejectExcel = (callback?: any) => {
cy.get('button', { timeout: longerCommandTimeout }) cy.get('button', { timeout: longerCommandTimeout })
.should('contain', 'Go to approvals screen') .should('contain', 'Approve')
.then((allButtons: any) => { .then((allButtons: any) => {
for (let approvalButton of allButtons) { for (let approvalButton of allButtons) {
if ( if (approvalButton.innerText.toLowerCase().includes('approve')) {
approvalButton.innerText
.toLowerCase()
.includes('go to approvals screen')
) {
approvalButton.click() approvalButton.click()
break break
} }

View File

@ -42,4 +42,4 @@ module.exports = function (config) {
} }
}, },
}); });
}; };

Binary file not shown.

View File

@ -10,7 +10,7 @@ const check = (cwd) => {
onlyAllow: onlyAllow:
'AFLv2.1;Apache 2.0;Apache-2.0;Apache*;Artistic-2.0;0BSD;BSD*;BSD-2-Clause;BSD-3-Clause;CC0-1.0;CC-BY-3.0;CC-BY-4.0;ISC;MIT;MPL-2.0;ODC-By-1.0;Python-2.0;Unlicense;', 'AFLv2.1;Apache 2.0;Apache-2.0;Apache*;Artistic-2.0;0BSD;BSD*;BSD-2-Clause;BSD-3-Clause;CC0-1.0;CC-BY-3.0;CC-BY-4.0;ISC;MIT;MPL-2.0;ODC-By-1.0;Python-2.0;Unlicense;',
excludePackages: excludePackages:
'@cds/city@1.1.0;@handsontable/angular@13.0.0;handsontable@13.0.0;hyperformula@2.5.0;jackspeak@2.2.0;path-scurry@1.7.0' '@cds/city@1.1.0;@handsontable/angular@14.3.0;handsontable@14.3.0;hyperformula@2.7.0;jackspeak@2.2.0;path-scurry@1.7.0'
}, },
(error, json) => { (error, json) => {
if (error) { if (error) {

23956
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "dc-client", "name": "data_controller-client",
"description": "dc-client", "description": "DataController Client",
"angular-cli": {}, "angular-cli": {},
"scripts": { "scripts": {
"start": "node --max_old_space_size=4096 node_modules/@angular/cli/bin/ng serve", "start": "node --max_old_space_size=4096 node_modules/@angular/cli/bin/ng serve",
@ -18,8 +18,8 @@
"deploy_sasjs": "rsync -avhe ssh ./dist/* --delete root@${npm_config_account}.4gl.io:/var/www/html/dc/dev", "deploy_sasjs": "rsync -avhe ssh ./dist/* --delete root@${npm_config_account}.4gl.io:/var/www/html/dc/dev",
"viyabuild": "cd build; ./viyabuild.sh", "viyabuild": "cd build; ./viyabuild.sh",
"lint": "cd .. && npm run lint", "lint": "cd .. && npm run lint",
"test": "ng test", "test": "npx ng test",
"test:headless": "ng test --browsers ChromeHeadless", "test:headless": "npx ng test --no-watch --no-progress --browsers ChromeHeadlessCI",
"watch": "ng test watch=true", "watch": "ng test watch=true",
"pree2e": "webdriver-manager update", "pree2e": "webdriver-manager update",
"e2e": "protractor protractor.config.js", "e2e": "protractor protractor.config.js",
@ -29,36 +29,39 @@
"cy:run": "cypress run", "cy:run": "cypress run",
"audit:prod": "npm audit --omit=dev", "audit:prod": "npm audit --omit=dev",
"sasdocs": "sasjs doc && ./sasjs/utils/deploydocs.sh", "sasdocs": "sasjs doc && ./sasjs/utils/deploydocs.sh",
"typedoc": "typedoc --options typedoc.json && cd ../tsdoc" "compodoc:build": "compodoc -p tsconfig.doc.json --name 'Data Controller Client'",
"compodoc:build-and-serve": "compodoc -p tsconfig.doc.json -s --name 'Data Controller Client'",
"compodoc:serve": "compodoc -s --name 'Data Controller Client'"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^16.1.2", "@angular/animations": "^17.3.3",
"@angular/cdk": "^15.2.0", "@angular/cdk": "^17.3.3",
"@angular/common": "^16.1.2", "@angular/common": "^17.3.3",
"@angular/compiler": "^16.1.2", "@angular/compiler": "^17.3.3",
"@angular/core": "^16.1.2", "@angular/core": "^17.3.3",
"@angular/forms": "^16.1.2", "@angular/forms": "^17.3.3",
"@angular/platform-browser": "^16.1.2", "@angular/platform-browser": "^17.3.3",
"@angular/platform-browser-dynamic": "^16.1.2", "@angular/platform-browser-dynamic": "^17.3.3",
"@angular/router": "^16.1.2", "@angular/router": "^17.3.3",
"@cds/core": "^6.4.2", "@cds/core": "^6.10.0",
"@clr/angular": "^13.17.0", "@clr/angular": "^17.0.1",
"@clr/icons": "^13.0.2", "@clr/icons": "^13.0.2",
"@clr/ui": "^13.17.0", "@clr/ui": "^17.0.1",
"@handsontable/angular": "^13.0.0", "@handsontable/angular": "^14.3.0",
"@sasjs/adapter": "4.3.6", "@sasjs/adapter": "4.10.2",
"@sasjs/utils": "^3.3.0", "@sasjs/utils": "^3.4.0",
"@sheet/crypto": "1.20211122.1", "@sheet/crypto": "file:libraries/sheet-crypto.tgz",
"@types/d3-graphviz": "^2.6.7", "@types/d3-graphviz": "^2.6.7",
"@sheet/crypto": "file:libraries/sheet-crypto.tgz",
"@types/text-encoding": "0.0.35", "@types/text-encoding": "0.0.35",
"base64-arraybuffer": "^0.2.0", "base64-arraybuffer": "^0.2.0",
"buffer": "^5.4.3", "buffer": "^5.4.3",
"crypto-browserify": "3.12.0", "crypto-browserify": "3.12.0",
"crypto-js": "^3.3.0", "crypto-js": "^4.2.0",
"d3-graphviz": "^5.0.2", "d3-graphviz": "^5.0.2",
"fs-extra": "^7.0.1", "fs-extra": "^7.0.1",
"handsontable": "^13.0.0", "handsontable": "^14.3.0",
"https-browserify": "1.0.0", "https-browserify": "1.0.0",
"hyperformula": "^2.5.0", "hyperformula": "^2.5.0",
"iconv-lite": "^0.5.0", "iconv-lite": "^0.5.0",
@ -76,22 +79,26 @@
"stream-http": "3.2.0", "stream-http": "3.2.0",
"text-encoding": "^0.7.0", "text-encoding": "^0.7.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.13.0" "vm": "^0.1.0",
"webpack": "^5.91.0",
"zone.js": "~0.14.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^16.1.0", "@angular-devkit/build-angular": "^17.3.3",
"@angular-eslint/builder": "16.0.3", "@angular-eslint/builder": "17.3.0",
"@angular-eslint/eslint-plugin": "16.0.3", "@angular-eslint/eslint-plugin": "17.3.0",
"@angular-eslint/eslint-plugin-template": "16.0.3", "@angular-eslint/eslint-plugin-template": "17.3.0",
"@angular-eslint/schematics": "16.0.3", "@angular-eslint/schematics": "17.3.0",
"@angular-eslint/template-parser": "16.0.3", "@angular-eslint/template-parser": "17.3.0",
"@angular/cli": "^16.1.0", "@angular/cli": "^17.3.3",
"@angular/compiler-cli": "^16.1.2", "@angular/compiler-cli": "^17.3.3",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@compodoc/compodoc": "^1.1.21",
"@cypress/webpack-preprocessor": "^5.17.1", "@cypress/webpack-preprocessor": "^5.17.1",
"@types/core-js": "^2.5.5", "@types/core-js": "^2.5.5",
"@types/crypto-js": "^4.0.1", "@types/crypto-js": "^4.2.1",
"@types/es6-shim": "^0.31.39", "@types/es6-shim": "^0.31.39",
"@types/jasmine": "~3.6.0", "@types/jasmine": "~5.1.4",
"@types/lodash-es": "^4.17.3", "@types/lodash-es": "^4.17.3",
"@types/marked": "^4.3.0", "@types/marked": "^4.3.0",
"@types/node": "12.20.50", "@types/node": "12.20.50",
@ -105,12 +112,12 @@
"es6-shim": "^0.35.5", "es6-shim": "^0.35.5",
"eslint": "^8.33.0", "eslint": "^8.33.0",
"git-describe": "^4.0.4", "git-describe": "^4.0.4",
"jasmine-core": "~3.6.0", "jasmine-core": "~5.1.2",
"karma": "~6.3.0", "karma": "~6.4.3",
"karma-chrome-launcher": "~3.1.0", "karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.1.0", "karma-coverage": "~2.2.1",
"karma-jasmine": "~4.0.0", "karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~1.7.0", "karma-jasmine-html-reporter": "~2.1.0",
"license-checker": "25.0.1", "license-checker": "25.0.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mochawesome": "^7.1.3", "mochawesome": "^7.1.3",
@ -119,9 +126,8 @@
"rimraf": "3.0.2", "rimraf": "3.0.2",
"ts-loader": "^9.2.8", "ts-loader": "^9.2.8",
"ts-node": "^3.3.0", "ts-node": "^3.3.0",
"typedoc": "^0.23.24", "typescript": "~5.4.4",
"typescript": "~4.9.4",
"wait-on": "^6.0.1", "wait-on": "^6.0.1",
"watch": "^1.0.2" "watch": "^1.0.2"
} }
} }

View File

@ -1,5 +1,8 @@
import { QueryClause } from './models/TableData' import { QueryClause } from './models/TableData'
/**
* Filtering cache info, to be reused when filtering modal is re-open
*/
interface FilterCache { interface FilterCache {
cols: any[] cols: any[]
vals: any[] vals: any[]
@ -10,12 +13,18 @@ interface FilterCache {
query: QueryClause[] query: QueryClause[]
} }
/**
* Filtering cache info in the open viewboxes, to be reused when filtering modal is re-open
*/
interface ViewboxCache { interface ViewboxCache {
[key: number]: { [key: number]: {
filter: FilterCache filter: FilterCache
} }
} }
/**
* Initial values when no cached values stored
*/
export const initFilter: { filter: FilterCache } = { export const initFilter: { filter: FilterCache } = {
filter: { filter: {
cols: <any[]>[], cols: <any[]>[],
@ -28,8 +37,23 @@ export const initFilter: { filter: FilterCache } = {
} }
} }
export interface XLMapListItem {
id: string
description: string
targetDS: string
}
/**
* Cached filtering values across whole app (editor, viewer, viewboxes)
* Cached lineage libraries, tables
* Cached metadata tree
* Cached usernav tree
* Cached viyaApi collections, search and selected endpoint
*/
export const globals: { export const globals: {
rootParam: string rootParam: string
dcLib: string
xlmaps: XLMapListItem[]
editor: any editor: any
viewer: any viewer: any
viewboxes: ViewboxCache viewboxes: ViewboxCache
@ -41,11 +65,13 @@ export const globals: {
[key: string]: any [key: string]: any
} = { } = {
rootParam: <string>'', rootParam: <string>'',
dcLib: '',
xlmaps: [],
editor: { editor: {
startupSet: <boolean>false, startupSet: <boolean>false,
treeNodeLibraries: <any[] | null>[], treeNodeLibraries: <any[] | null>[],
libsAndTables: <any[]>[], libsAndTables: <any[]>[],
libraries: <String[] | undefined>[], libraries: <string[] | undefined>[],
library: <string>'', library: <string>'',
table: <string>'', table: <string>'',
filter: <FilterCache>{ filter: <FilterCache>{

View File

@ -1,40 +0,0 @@
<div class="content-area">
<div class="card">
<div class="card-header d-flex flex-column justify-content-center">
<h3 class="text-center">
You succesfully edited table
<span class="color-blue font-weight-700">{{ libds }}</span>
</h3>
<p class="text-center">
<b>Please choose from the following actions</b>
</p>
<div class="row d-flex justify-content-center mt-20">
<button
class="btn btn-sm btn-outline text-center"
(click)="submittedTableScreen()"
>
Go to submitted table screen
</button>
<button
class="btn btn-sm btn-outline text-center"
(click)="viewerTableScreen()"
>
Go to base table screen
</button>
<button
id="approvalBtn"
class="btn btn-sm btn-success-outline text-center"
(click)="approveTableScreen()"
>
Go to approvals screen
</button>
<button
class="btn btn-sm btn-info-outline text-center"
(click)="goBack()"
>
Go back to editor
</button>
</div>
</div>
</div>
</div>

View File

@ -1,50 +0,0 @@
import { AfterViewInit, Component, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
@Component({
selector: 'app-actions',
templateUrl: './actions.component.html',
styleUrls: ['./actions.component.scss'],
host: {
class: 'content-container'
}
})
export class ActionsComponent implements OnInit, AfterViewInit {
public dsid: any
public libds: string | undefined
constructor(
private route: ActivatedRoute,
private router: Router
) {}
public submittedTableScreen() {
this.router.navigateByUrl('/stage/' + this.dsid)
}
public approveTableScreen() {
this.router.navigateByUrl('/approve/approveDet/' + this.dsid)
}
public viewerTableScreen() {
this.router.navigateByUrl('/view/data/' + this.libds)
}
public goBack() {
this.router.navigateByUrl('/editor/' + this.libds)
}
async ngOnInit() {
this.dsid = this.route.snapshot.params['dsid']
this.libds = this.route.snapshot.params['libds']
}
ngAfterViewInit() {
setTimeout(() => {
let approvalBtn: any = window.document.getElementById('approvalBtn')
if (!!approvalBtn) {
approvalBtn.focus()
}
}, 700)
}
}

View File

@ -12,7 +12,7 @@
<div class="alert-items"> <div class="alert-items">
<div class="alert-item static"> <div class="alert-item static">
<div class="alert-icon-wrapper"> <div class="alert-icon-wrapper">
<clr-icon class="mt-2" shape="warning-standard"></clr-icon> <cds-icon class="alert-icon" shape="warning-standard"></cds-icon>
</div> </div>
<div class="alert-text"> <div class="alert-text">
Data Controller (FREE Tier) - to upgrade contact Data Controller (FREE Tier) - to upgrade contact
@ -30,7 +30,7 @@
<div class="alert-items"> <div class="alert-items">
<div class="alert-item static"> <div class="alert-item static">
<div class="alert-icon-wrapper"> <div class="alert-icon-wrapper">
<clr-icon class="mt-2" shape="warning-standard"></clr-icon> <cds-icon class="alert-icon" shape="warning-standard"></cds-icon>
</div> </div>
<div class="alert-text"> <div class="alert-text">
Data Controller (FREE Tier) - Problem with licence Data Controller (FREE Tier) - Problem with licence
@ -55,7 +55,7 @@
<div class="alert-items"> <div class="alert-items">
<div class="alert-item static"> <div class="alert-item static">
<div class="alert-icon-wrapper"> <div class="alert-icon-wrapper">
<clr-icon class="mt-2" shape="warning-standard"></clr-icon> <cds-icon class="alert-icon" shape="warning-standard"></cds-icon>
</div> </div>
<div class="alert-text"> <div class="alert-text">
@ -85,7 +85,7 @@
<div class="alert-items"> <div class="alert-items">
<div class="alert-item static"> <div class="alert-item static">
<div class="alert-icon-wrapper"> <div class="alert-icon-wrapper">
<clr-icon class="mt-2" shape="warning-standard"></clr-icon> <cds-icon class="alert-icon" shape="warning-standard"></cds-icon>
</div> </div>
<div class="alert-text"> <div class="alert-text">
@ -168,8 +168,8 @@
</button> </button>
<clr-dropdown-menu *clrIfOpen clrPosition="bottom-left"> <clr-dropdown-menu *clrIfOpen clrPosition="bottom-left">
<a [routerLink]="['/view']" clrDropdownItem>VIEW</a> <a [routerLink]="['/view']" clrDropdownItem>VIEW</a>
<a [routerLink]="['/home']" clrDropdownItem>EDIT</a> <a [routerLink]="['/home']" clrDropdownItem>LOAD</a>
<a [routerLink]="['/submitted']" clrDropdownItem>REVIEW</a> <a [routerLink]="['/review/submitted']" clrDropdownItem>REVIEW</a>
</clr-dropdown-menu> </clr-dropdown-menu>
</clr-dropdown> </clr-dropdown>
</div> </div>
@ -189,10 +189,10 @@
router.url.includes('edit-record') || router.url.includes('edit-record') ||
router.url.includes('home') router.url.includes('home')
" "
>EDIT</a >LOAD</a
> >
<a <a
[routerLink]="['/submitted']" [routerLink]="['/review/submitted']"
[class.active]=" [class.active]="
router.url.includes('submitted') || router.url.includes('submitted') ||
router.url.includes('approve') || router.url.includes('approve') ||
@ -204,14 +204,7 @@
</div> </div>
</ng-container> </ng-container>
<div class="header-actions"> <app-header-actions></app-header-actions>
<div class="nav-text">
<app-loading-indicator></app-loading-indicator>
</div>
<div class="dropdown">
<app-user-nav-dropdown></app-user-nav-dropdown>
</div>
</div>
</header> </header>
<nav <nav
*ngIf=" *ngIf="
@ -224,7 +217,7 @@
<ul class="nav"> <ul class="nav">
<li class="nav-item"> <li class="nav-item">
<a <a
[routerLink]="['/submitted']" [routerLink]="['/review/submitted']"
class="nav-link nav-text" class="nav-link nav-text"
routerLinkActive="active" routerLinkActive="active"
>SUBMIT</a >SUBMIT</a
@ -232,15 +225,16 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a <a
[routerLink]="['/approve']" [routerLink]="['/review/approve']"
class="nav-link nav-text" class="nav-link nav-text"
[class.active]="router.url.includes('approve')"
routerLinkActive="active" routerLinkActive="active"
>APPROVE</a >APPROVE</a
> >
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a <a
[routerLink]="['/history']" [routerLink]="['/review/history']"
class="nav-link nav-text" class="nav-link nav-text"
routerLinkActive="active" routerLinkActive="active"
>HISTORY</a >HISTORY</a

View File

@ -1,3 +1,5 @@
@import '../colors.scss';
// Copyright (c) 2016 VMware, Inc. All Rights Reserved. // Copyright (c) 2016 VMware, Inc. All Rights Reserved.
// This software is released under MIT license. // This software is released under MIT license.
// The full license information can be found in LICENSE in the root directory of this project. // The full license information can be found in LICENSE in the root directory of this project.
@ -6,7 +8,7 @@ app-requests-modal {
} }
header.app-header { header.app-header {
background: #314351 !important; background: $headerBackground !important;
color: #fff; color: #fff;
} }
@ -42,7 +44,7 @@ header.app-header {
align-items: center; align-items: center;
padding: 30px; padding: 30px;
z-index: 110; z-index: 110;
background: #314351; background: $headerBackground;
.expired-notice { .expired-notice {
color: #e0e0e0; color: #e0e0e0;
@ -91,33 +93,12 @@ header {
} }
} }
.nav .nav-link:hover {
.nav-link {
color: #fafafa;
opacity: .9;
line-height: 1.45rem;
}
.nav .nav-link:hover {
box-shadow: inset 0 -3px 0 transparent;
transition: box-shadow .2s ease-in;
}
.nav
.nav-link:hover {
color: #fafafa; color: #fafafa;
opacity: 1;
} }
.nav .nav-link.active { .nav-link.active {
background: #61717D; background: #61717D;
opacity: 1;
box-shadow: inset 0 -3px transparent;
// padding: 0 1rem 0 1rem;
}
.nav .nav-item {
margin-right: 1rem;
} }
} }
@ -127,15 +108,6 @@ header {
font-size: 12px; font-size: 12px;
} }
.btn.btn-success {
border-color: #62a420;
background-color: #16a57a!important;
color: #fff;
}
.btn.btn-success:hover {
background-color: #2add39;
color: #fff;
}
.toggle-switch input[type=checkbox]:checked+label:before { .toggle-switch input[type=checkbox]:checked+label:before {
border-color: #61717D; border-color: #61717D;
@ -163,59 +135,44 @@ header {
color: #fff; color: #fff;
} }
@media screen and (max-width: 768px) {
.navBarResp {
display: flex;
justify-content: flex-start;
background: #495A67;
color: #fff;
}
.main-container .sub-nav.clr-nav-level-1 .nav .nav-link, .main-container .sub-nav.clr-nav-level-2 .nav .nav-link, .main-container .subnav.clr-nav-level-1 .nav .nav-link, .main-container .subnav.clr-nav-level-2 .nav .nav-link {
padding: 0 .5rem 0 1rem;
width: 100%;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
border-radius: .125rem 0 0 .125rem;
color: #95c84b;
}
.card-block, .card-footer {
padding: 10px 0px 0px 0px;
}
.main-container[_ngcontent-c0] .content-container[_ngcontent-c0] .content-area[_ngcontent-c0] {
padding: 0rem 0rem 0rem 0rem;
}
}
::ng-deep { ::ng-deep {
.htInvalid { .htInvalid {
background: black!important; background: black!important;
} }
@media screen and (max-width:480px) { @media screen and (max-width:480px) {
h2 { h2 {
font-size: .7rem!important; font-size: .7rem!important;
}
h3 {
font-size: .7rem;
}
} }
h3 {
font-size: .7rem;
}
}
.nav-link { .nav-link {
padding: 0rem 1rem 0rem 1rem; padding: 0rem 1rem 0rem 1rem;
} }
.btn-primary .btn, .btn.btn-primary { body[cds-theme="light"] {
border-color: #314351; .btn-primary .btn, .btn.btn-primary {
background-color: #314351; border-color: $headerBackground;
color: #fff; background-color: $headerBackground;
color: #fff;
}
} }
body[cds-theme="dark"] {
.btn-primary .btn, .btn.btn-primary {
border-color: #5e7382;
background-color: #5e7382;
color: #fff;
clr-icon, cds-icon {
color: #fff
}
}
}
.btn { .btn {
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
@ -236,36 +193,32 @@ header {
font-weight: 500; font-weight: 500;
height: 1.5rem; height: 1.5rem;
padding: 0 .5rem; padding: 0 .5rem;
border-color: #314351;
background-color: transparent;
color: #314351;
}
.btn.btn-outline {
border-color: #314351;
background-color: transparent;
color: #314351;
} }
.btn.btn-outline:hover { .btn.btn-outline:hover {
border-color: #314351; border-color: $headerBackground;
background-color: #495A67; background-color: #495A67;
color: #fff; color: #fff;
} }
.btn.btn-success-outline:hover {
background-color: #5ea71f;
color: #fff7f7;
border-color: #9a9696;
}
// .btn.btn-success-outline {
// border-color: #266900;
// background-color: transparent;
// color: #318700;
// }
// .wtSpreader {
// } body[cds-theme="dark"] {
.btn.btn-icon.btn-dimmed {
color: #7295ae;
}
}
body[cds-theme="light"] {
.btn.btn-icon.btn-dimmed {
color: $headerBackground;
}
.btn.btn-outline {
border-color: $headerBackground;
background-color: transparent;
color: $headerBackground;
}
}
.htMobileEditorContainer .inputs textarea { .htMobileEditorContainer .inputs textarea {
font-size: 13pt; font-size: 13pt;
@ -298,65 +251,68 @@ header {
width: 350px; width: 350px;
} }
.handsontable {
background-color: #ffffff;
// border: 1px solid #ccc;
border-radius: 3px;
}
.handsontable th {
background-color: #fafafa;
}
/* Left and right */ /* Left and right */
.ht_clone_left th {
border-right: 1px solid #ccc;
border-left: 1px solid #ccc;
}
/* Column headers */ /* Column headers */
.ht_clone_top th {
border-top: 1px solid #ccc; body[cds-theme="light"] {
border-right: 1px solid #ccc; .wtBorder {
border-bottom: 1px solid #ccc; background-color: #495A67!important;
}
.ht_master tr:nth-of-type(odd) > td {
filter: brightness(0.95);
}
} }
.ht_clone_top_left_corner th { $darkBorderColor: #697c85;
border-right: 1px solid #ccc;
}
.ht_master tr:nth-of-type(odd) > td { body[cds-theme="dark"] {
background-color: #f3f3f3; .ht_master tr:nth-of-type(odd) > td {
border: 1px solid rgb(197, 197, 197); filter: brightness(1.2);
border-bottom: 1px solid rgb(236, 235, 235); }
// padding: 1px 1px;
}
.ht_master tr:nth-of-type(even) > td { .ht_master:not(.emptyColumns) ~ .handsontable tbody tr th, .ht_master:not(.emptyColumns) ~ .handsontable:not(.ht_clone_top) thead tr th:first-child {
background-color: white; background-color: #2d4048;
border: 1px solid rgb(197, 197, 197); border-color: $darkBorderColor;
border-bottom: 1px solid rgb(236, 235, 235); }
// padding: 1px 1px;
}
.wtBorder { .handsontable td {
background-color: #495A67!important; // border-right: 1px solid #697c85;
// border-bottom: 1px solid #697c85;
border-color: $darkBorderColor;
}
.handsontable tr:first-child th, .handsontable tr:first-child td {
border-color: $darkBorderColor;
}
.handsontable .handsontable.ht_clone_top .wtHider {
border-color: $darkBorderColor;
}
.handsontable .changeType {
background-color: #3c5662;
border-color: $darkBorderColor;
}
.handsontableInput {
background-color: #708b98;
}
} }
.handsontable .handsontable.ht_clone_top .wtHider { .handsontable .handsontable.ht_clone_top .wtHider {
padding: 0 0 0px 0!important; padding: 0 0 0px 0!important;
margin: 0px; margin: 0px;
border-bottom: 3px solid #d6d3d3; border-bottom: 3px solid #d6d3d3;
}
.content-container {
background: #F5F6FF;
} }
.card { body[cds-theme="light"] {
box-shadow: 0 0.125rem 0 0 #d7d7d7; .content-container {
border-radius: .0rem; // background: red;
border: 1px solid transparent; background: #F5F6FF;
// min-height: calc(100vh - 150px); }
} }
.datagrid-compact, .datagrid-history{ .datagrid-compact, .datagrid-history{
@ -364,8 +320,6 @@ header {
border-collapse: separate; border-collapse: separate;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: .125rem; border-radius: .125rem;
background-color: #fff;
color: #565656;
margin: 0; margin: 0;
margin-top: 1rem; margin-top: 1rem;
max-width: 100%; max-width: 100%;
@ -387,8 +341,8 @@ header {
} }
.datagrid-footer { .datagrid-footer {
position: absolute; position: absolute;
right: 15px; right: 30px;
top: 2px; top: 1px;
} }
.datagrid .datagrid-head { .datagrid .datagrid-head {
background-color: #fff; background-color: #fff;
@ -408,7 +362,6 @@ header {
-webkit-box-direction: normal; -webkit-box-direction: normal;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
background: #f5f6ff;
padding: .5rem 0; padding: .5rem 0;
border: 1px solid #ccc; border: 1px solid #ccc;
box-shadow: 0 1px 0.125rem hsla(0,0%,45%,.25); box-shadow: 0 1px 0.125rem hsla(0,0%,45%,.25);
@ -423,8 +376,6 @@ header {
border-collapse: separate; border-collapse: separate;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 0px; border-radius: 0px;
background-color: #fff;
color: #565656;
margin: 0; margin: 0;
margin-top: 1rem; margin-top: 1rem;
max-width: 100%; max-width: 100%;
@ -435,7 +386,6 @@ header {
font-size: .45833rem; font-size: .45833rem;
font-weight: 600; font-weight: 600;
letter-spacing: .03em; letter-spacing: .03em;
background-color: #fff;
vertical-align: bottom; vertical-align: bottom;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
text-transform: uppercase; text-transform: uppercase;
@ -458,4 +408,34 @@ header {
max-width: 400px; max-width: 400px;
width: 100%; width: 100%;
} }
}
@media screen and (max-width: 768px) {
.navBarResp {
display: flex;
justify-content: flex-start;
background: #495A67;
color: #fff;
}
.main-container .sub-nav.clr-nav-level-1 .nav .nav-link, .main-container .sub-nav.clr-nav-level-2 .nav .nav-link, .main-container .subnav.clr-nav-level-1 .nav .nav-link, .main-container .subnav.clr-nav-level-2 .nav .nav-link {
padding: 0 .5rem 0 1rem;
width: 100%;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
border-radius: .125rem 0 0 .125rem;
color: #95c84b;
}
.card-block, .card-footer {
padding: 10px 0px 0px 0px;
}
.main-container[_ngcontent-c0] .content-container[_ngcontent-c0] .content-area[_ngcontent-c0] {
padding: 0rem 0rem 0rem 0rem;
}
} }

View File

@ -13,6 +13,15 @@ import { InfoModal } from './models/InfoModal'
import { DcAdapterSettings } from './models/DcAdapterSettings' import { DcAdapterSettings } from './models/DcAdapterSettings'
import { AppStoreService } from './services/app-store.service' import { AppStoreService } from './services/app-store.service'
import { LicenceService } from './services/licence.service' import { LicenceService } from './services/licence.service'
import '@cds/core/icon/register.js'
import {
ClarityIcons,
exclamationTriangleIcon,
moonIcon,
sunIcon
} from '@cds/core/icon'
ClarityIcons.addIcons(moonIcon, sunIcon, exclamationTriangleIcon)
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
@ -57,24 +66,15 @@ export class AppComponent {
private elementRef: ElementRef private elementRef: ElementRef
) { ) {
this.parseDcAdapterSettings() this.parseDcAdapterSettings()
/**
* Prints app info in the console such as:
* - Adapter versions
* - App version
* - Build timestamp
*
*/
;(window as any).appinfo = () => { ;(window as any).appinfo = () => {
const licenseKeyData = this.licenceService.getLicenseKeyData()
if (licenseKeyData) {
const expiry_date = moment(
licenseKeyData.valid_until,
'YYYY-MM-DD'
).startOf('day')
const current_date = moment().startOf('day')
const daysToExpiry = expiry_date.diff(current_date, 'days')
licenseKeyData.valid_until += ` (${daysToExpiry} ${
daysToExpiry === 1 ? 'day' : 'days'
} remaining)`
if (isNaN(daysToExpiry)) licenseKeyData.valid_until = 'Unlimited'
}
console.table({ console.table({
'Adapter version': VERSION.adapterVersion || 'n/a', 'Adapter version': VERSION.adapterVersion || 'n/a',
'App version': (VERSION.tag || '').replace('v', ''), 'App version': (VERSION.tag || '').replace('v', ''),
@ -87,7 +87,12 @@ export class AppComponent {
this.subscribeToLicenseEvents() this.subscribeToLicenseEvents()
/**
* Fetches git tag ang git hash from `version.ts` file
* It's placed in the user drop down.
*/
this.commitVer = (VERSION.tag || '').replace('v', '') + '.' + VERSION.hash this.commitVer = (VERSION.tag || '').replace('v', '') + '.' + VERSION.hash
router.events.subscribe((val) => { router.events.subscribe((val) => {
this.routeUrl = this.router.url this.routeUrl = this.router.url
@ -127,8 +132,10 @@ export class AppComponent {
this.subscribeToAppActive() this.subscribeToAppActive()
this.subscribeToDemoLimitModal() this.subscribeToDemoLimitModal()
/* In Viya streaming apps, content is served within an iframe. This code /**
makes that iframe "full screen" so it looks like a regular window. */ * In Viya streaming apps, content is served within an iframe. This code
* makes that iframe "full screen" so it looks like a regular window.
*/
if (window.frameElement) { if (window.frameElement) {
window.frameElement.setAttribute( window.frameElement.setAttribute(
'style', 'style',
@ -143,6 +150,9 @@ export class AppComponent {
} }
} }
/**
* Parses adapter settings that are found in the <sasjs> tag inside index.html
*/
private parseDcAdapterSettings() { private parseDcAdapterSettings() {
const sasjsElement = document.querySelector('sasjs') const sasjsElement = document.querySelector('sasjs')
@ -180,9 +190,14 @@ export class AppComponent {
this.appService.sasServiceInit() this.appService.sasServiceInit()
} }
/**
* Opens licence page with the active licence problem
* Problem details are encoded in the url
*/
public licenceProblemDetails(url: string) { public licenceProblemDetails(url: string) {
this.router.navigateByUrl(url) this.router.navigateByUrl(url)
} }
/** /**
* Based on string provided we return true, false or null * Based on string provided we return true, false or null
* True -> Compute API * True -> Compute API
@ -199,6 +214,12 @@ export class AppComponent {
return value === 'true' || false return value === 'true' || false
} }
/**
* Listens for an `demo limit` event that will show the `Feature locked modal`
* For exmaple when in editor upload feature is not enabled
* When user tries to upload the excel, editor component will trgger this event
* And stop the execution of file upload code.
*/
public subscribeToDemoLimitModal() { public subscribeToDemoLimitModal() {
this.eventService.onDemoLimitModalShow.subscribe((featureName: string) => { this.eventService.onDemoLimitModalShow.subscribe((featureName: string) => {
this.demoLimitNotice = { this.demoLimitNotice = {
@ -208,6 +229,10 @@ export class AppComponent {
}) })
} }
/**
* Listens for licence events so banner can be displayed.
* App is free tier, licence will expire, is expired or is invalid
*/
public subscribeToLicenseEvents() { public subscribeToLicenseEvents() {
this.licenceService.isAppFreeTier.subscribe((isAppFreeTier: boolean) => { this.licenceService.isAppFreeTier.subscribe((isAppFreeTier: boolean) => {
this.freeTierBanner = isAppFreeTier this.freeTierBanner = isAppFreeTier
@ -227,6 +252,10 @@ export class AppComponent {
) )
} }
/**
* Listens for an event that will activate od deactivate full application.
* Based on licence key prcoessing result
*/
public subscribeToAppActive() { public subscribeToAppActive() {
this.licenceService.isAppActivated.subscribe((value: any) => { this.licenceService.isAppActivated.subscribe((value: any) => {
this.appActive = value this.appActive = value
@ -248,31 +277,51 @@ export class AppComponent {
}) })
} }
/**
* When startupservice request is finished with valid response, this event will
* make sure loading screen is gone.
*/
public subscribeToStartupData() { public subscribeToStartupData() {
this.eventService.onStartupDataLoaded.subscribe(() => { this.eventService.onStartupDataLoaded.subscribe(() => {
this.startupDataLoaded = true this.startupDataLoaded = true
}) })
} }
/**
* Opens requests modal when requested from event service
*/
public subscribeToRequestsModal() { public subscribeToRequestsModal() {
this.eventService.onRequestsModalOpen.subscribe((value: boolean) => { this.eventService.onRequestsModalOpen.subscribe((value: boolean) => {
this.requestsModal = true this.requestsModal = true
}) })
} }
/**
* Closes abort modal with matching ID (there could be multiple abort modals open)
*/
public closeAbortModal(abortId: number) { public closeAbortModal(abortId: number) {
let abortIndex = this.sasjsAborts.findIndex((abort) => abort.id === abortId) let abortIndex = this.sasjsAborts.findIndex((abort) => abort.id === abortId)
this.sasjsAborts.splice(abortIndex, 1) this.sasjsAborts.splice(abortIndex, 1)
} }
/**
* Toggles sidebar when requested from event service
*/
public toggleSidebar() { public toggleSidebar() {
this.eventService.toggleSidebar() this.eventService.toggleSidebar()
} }
/**
* Whether or not current route includes the route from param
* @param route route to check
*/
public isMainRoute(route: string): boolean { public isMainRoute(route: string): boolean {
return this.router.url.includes(route) return this.router.url.includes(route)
} }
/**
* Opens a page for updating the licence.
*/
public openLicencingPage() { public openLicencingPage() {
this.router.navigateByUrl('/licensing/update') this.router.navigateByUrl('/licensing/update')
} }

View File

@ -11,62 +11,29 @@ import { NotFoundComponent } from './not-found/not-found.component'
import { SasStoreService } from './services/sas-store.service' import { SasStoreService } from './services/sas-store.service'
import { SharedModule } from './shared/shared.module' import { SharedModule } from './shared/shared.module'
// import { EditorComponent } from './editor/editor.component'
import { ActionsComponent } from './actions/actions.component'
import { AppSharedModule } from './app-shared.module' import { AppSharedModule } from './app-shared.module'
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
import { ApproveComponent } from './approve/approve.component'
import { DeployComponent } from './deploy/deploy.component'
import { AutomaticComponent } from './deploy/sections/automatic/automatic.component'
import { ManualComponent } from './deploy/sections/manual/manual.component'
import { SasjsConfiguratorComponent } from './deploy/sections/sasjs-configurator/sasjs-configurator.component'
import { GroupComponent } from './group/group.component'
import { HistoryComponent } from './history/history.component'
import { LicensingComponent } from './licensing/licensing.component'
import { LineageComponent } from './lineage/lineage.component'
import { MetadataComponent } from './metadata/metadata.component'
import { PipesModule } from './pipes/pipes.module' import { PipesModule } from './pipes/pipes.module'
import { RoleComponent } from './role/role.component' import { ReviewRouteComponent } from './routes/review-route/review-route.component'
import { ApproveRouteComponent } from './routes/approve-route/approve-route.component'
import { HistoryRouteComponent } from './routes/history-route/history-route.component'
import { LicensingGuard } from './routes/licensing.guard' import { LicensingGuard } from './routes/licensing.guard'
import { UsernavRouteComponent } from './routes/usernav-route/usernav-route.component' import { UsernavRouteComponent } from './routes/usernav-route/usernav-route.component'
import { AppService } from './services/app.service' import { AppService } from './services/app.service'
import { InfoModalComponent } from './shared/abort-modal/info-modal.component' import { InfoModalComponent } from './shared/abort-modal/info-modal.component'
import { RequestsModalComponent } from './shared/requests-modal/requests-modal.component' import { RequestsModalComponent } from './shared/requests-modal/requests-modal.component'
import { SubmitterComponent } from './submitter/submitter.component'
import { UserComponent } from './user/user.component'
import { HomeModule } from './home/home.module'
import { SystemComponent } from './system/system.component'
import { DirectivesModule } from './directives/directives.module' import { DirectivesModule } from './directives/directives.module'
import { ViyaApiExplorerComponent } from './viya-api-explorer/viya-api-explorer.component' import { ViyaApiExplorerComponent } from './viya-api-explorer/viya-api-explorer.component'
import { NgxJsonViewerModule } from 'ngx-json-viewer' import { NgxJsonViewerModule } from 'ngx-json-viewer'
import { AppSettingsService } from './services/app-settings.service'
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
NotFoundComponent, NotFoundComponent,
ApproveComponent, ReviewRouteComponent,
ApproveDetailsComponent, ReviewRouteComponent,
ActionsComponent,
HistoryComponent,
LineageComponent,
SubmitterComponent,
ApproveRouteComponent,
HistoryRouteComponent,
MetadataComponent,
UsernavRouteComponent, UsernavRouteComponent,
UserComponent,
GroupComponent,
RoleComponent,
RequestsModalComponent, RequestsModalComponent,
DeployComponent,
InfoModalComponent, InfoModalComponent,
LicensingComponent,
ManualComponent,
AutomaticComponent,
SasjsConfiguratorComponent,
SystemComponent,
ViyaApiExplorerComponent ViyaApiExplorerComponent
], ],
imports: [ imports: [
@ -79,12 +46,11 @@ import { NgxJsonViewerModule } from 'ngx-json-viewer'
SharedModule, SharedModule,
ClarityModule, ClarityModule,
AppSharedModule, AppSharedModule,
HomeModule,
PipesModule, PipesModule,
DirectivesModule, DirectivesModule,
NgxJsonViewerModule NgxJsonViewerModule
], ],
providers: [AppService, SasStoreService, ApproveComponent, LicensingGuard], providers: [AppService, SasStoreService, LicensingGuard, AppSettingsService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule {} export class AppModule {}

View File

@ -4,25 +4,23 @@
* The full license information can be found in LICENSE in the root directory of this project. * The full license information can be found in LICENSE in the root directory of this project.
*/ */
import { ModuleWithProviders } from '@angular/core' import { ModuleWithProviders } from '@angular/core'
import { Routes, RouterModule } from '@angular/router' import { RouterModule, Routes } from '@angular/router'
import { HomeComponent } from './home/home.component'
import { ApproveComponent } from './approve/approve.component'
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
import { ActionsComponent } from './actions/actions.component'
import { HistoryComponent } from './history/history.component'
import { NotFoundComponent } from './not-found/not-found.component' import { NotFoundComponent } from './not-found/not-found.component'
import { SubmitterComponent } from './submitter/submitter.component'
import { ApproveRouteComponent } from './routes/approve-route/approve-route.component' import { DeployModule } from './deploy/deploy.module'
import { DeployComponent } from './deploy/deploy.component'
import { LicensingComponent } from './licensing/licensing.component'
import { LicensingGuard } from './routes/licensing.guard'
import { StageModule } from './stage/stage.module'
import { EditorModule } from './editor/editor.module' import { EditorModule } from './editor/editor.module'
import { HomeModule } from './home/home.module'
import { LicensingModule } from './licensing/licensing.module'
import { ReviewModule } from './review/review.module'
import { ReviewRouteComponent } from './routes/review-route/review-route.component'
import { StageModule } from './stage/stage.module'
import { SystemModule } from './system/system.module'
import { ViewerModule } from './viewer/viewer.module' import { ViewerModule } from './viewer/viewer.module'
import { SystemComponent } from './system/system.component'
/**
* Defining routes
*/
export const ROUTES: Routes = [ export const ROUTES: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '', redirectTo: 'home', pathMatch: 'full' },
{ {
@ -30,23 +28,31 @@ export const ROUTES: Routes = [
loadChildren: () => ViewerModule loadChildren: () => ViewerModule
}, },
{ {
path: 'approve', /**
component: ApproveRouteComponent, * Load review module (approve, history, submitted)
*/
path: 'review',
component: ReviewRouteComponent,
children: [ children: [
{ path: '', pathMatch: 'full', redirectTo: 'toapprove' }, { path: '', pathMatch: 'full', redirectTo: 'toapprove' },
{ path: 'toapprove', component: ApproveComponent }, {
{ path: 'approveDet/:tableId', component: ApproveDetailsComponent }, path: '',
{ path: 'submitted', component: SubmitterComponent } loadChildren: () => ReviewModule
}
] ]
}, },
{ {
path: 'licensing/:action', path: 'licensing',
component: LicensingComponent, loadChildren: () => LicensingModule
canActivate: [LicensingGuard],
canDeactivate: [LicensingGuard]
}, },
{ path: 'home', component: HomeComponent },
{ {
path: 'home',
loadChildren: () => HomeModule
},
{
/**
* Load editor module with subroutes
*/
path: 'editor', path: 'editor',
loadChildren: () => EditorModule loadChildren: () => EditorModule
}, },
@ -54,16 +60,20 @@ export const ROUTES: Routes = [
path: 'stage', path: 'stage',
loadChildren: () => StageModule loadChildren: () => StageModule
}, },
{ path: 'system', component: SystemComponent }, {
{ path: 'actions/:libds/:dsid', component: ActionsComponent }, path: 'system',
{ path: 'history', component: HistoryComponent }, loadChildren: () => SystemModule
{ path: 'submitted', component: SubmitterComponent }, },
{ path: 'submitted/:tableId', component: SubmitterComponent }, {
{ path: 'deploy', component: DeployComponent }, path: 'deploy',
{ path: 'deploy/manualdeploy', component: DeployComponent }, loadChildren: () => DeployModule
},
{ path: '**', component: NotFoundComponent } { path: '**', component: NotFoundComponent }
] ]
/**
* Exporting routes
*/
export const ROUTING: ModuleWithProviders<RouterModule> = RouterModule.forRoot( export const ROUTING: ModuleWithProviders<RouterModule> = RouterModule.forRoot(
ROUTES, ROUTES,
{ useHash: true } { useHash: true }

View File

@ -0,0 +1,14 @@
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { DeployComponent } from './deploy.component'
const routes: Routes = [
{ path: '', component: DeployComponent },
{ path: 'manualdeploy', component: DeployComponent }
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DeployRoutingModule {}

View File

@ -78,6 +78,9 @@ export class DeployComponent implements OnInit {
this.setDeployDefaults() this.setDeployDefaults()
} }
/**
* Setting default values used for deploy request
*/
public setDeployDefaults() { public setDeployDefaults() {
this.dcPath = this.dcAdapterSettings?.dcPath || '' this.dcPath = this.dcAdapterSettings?.dcPath || ''
this.selectedAdminGroup = this.dcAdapterSettings?.adminGroup || '' this.selectedAdminGroup = this.dcAdapterSettings?.adminGroup || ''
@ -86,6 +89,9 @@ export class DeployComponent implements OnInit {
} }
} }
/**
* Accepting terms of service shows next screen
*/
public termsAgreeChange() { public termsAgreeChange() {
if (!this.autodeploy) { if (!this.autodeploy) {
this.getAdminGroups() this.getAdminGroups()
@ -94,6 +100,9 @@ export class DeployComponent implements OnInit {
this.step++ this.step++
} }
/**
* Fetches admin groups from VIYA to be selected for a backend deploy
*/
public getAdminGroups() { public getAdminGroups() {
fetch( fetch(
this.sasJsConfig.serverUrl + '/identities/groups?sortBy=name&limit=5000', this.sasJsConfig.serverUrl + '/identities/groups?sortBy=name&limit=5000',

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { DeployComponent } from './deploy.component'
import { AutomaticComponent } from './sections/automatic/automatic.component'
import { ManualComponent } from './sections/manual/manual.component'
import { SasjsConfiguratorComponent } from './sections/sasjs-configurator/sasjs-configurator.component'
import { ClarityModule } from '@clr/angular'
import { FormsModule } from '@angular/forms'
import { DeployRoutingModule } from './deploy-routing.module'
@NgModule({
declarations: [
DeployComponent,
AutomaticComponent,
ManualComponent,
SasjsConfiguratorComponent
],
imports: [CommonModule, FormsModule, ClarityModule, DeployRoutingModule]
})
export class DeployModule {}

View File

@ -55,6 +55,13 @@ export class AutomaticComponent implements OnInit {
ngOnInit(): void {} ngOnInit(): void {}
/**
* Executes sas.json file to deploy the backend
* Method will first try to run the `auto deploy`
* If that fails the rest of the code is ignored.
* If request is successfull, method will continue to try
* to create database if checkbox is toggled on
*/
public async executeJson() { public async executeJson() {
this.autodeploying = true this.autodeploying = true
this.isSubmittingJson = true this.isSubmittingJson = true
@ -99,6 +106,9 @@ export class AutomaticComponent implements OnInit {
} }
} }
/**
* Runs the `makedata` request sending the ADMIN and DCPATH values
*/
public createDatabase() { public createDatabase() {
let data = { let data = {
fromjs: [ fromjs: [

View File

@ -52,6 +52,9 @@ export class ManualComponent implements OnInit {
ngOnInit(): void {} ngOnInit(): void {}
/**
* FIXME: Remove
*/
public async executableContext() { public async executableContext() {
// getExecutableContexts now need AuthConfig parameter which we don't have on web // getExecutableContexts now need AuthConfig parameter which we don't have on web
// this.contextsLoading = true // this.contextsLoading = true
@ -65,10 +68,16 @@ export class ManualComponent implements OnInit {
// this.contextsLoading = false // this.contextsLoading = false
} }
/**
* Removes sas.json file attached to the input
*/
public clearUploadInput(event: Event) { public clearUploadInput(event: Event) {
this.deployService.clearUploadInput(event) this.deployService.clearUploadInput(event)
} }
/**
* Reads attached SAS file to be sent to sas for execution (backend deploy)
*/
public onSasFileChange(event: any) { public onSasFileChange(event: any) {
this.preloadedFile = false this.preloadedFile = false
@ -93,12 +102,18 @@ export class ManualComponent implements OnInit {
fileReader.readAsText(file) fileReader.readAsText(file)
} }
/**
* Reads attached JSON file to be sent to sas for execution (backend deploy)
*/
public async onJsonFileChange(event: any) { public async onJsonFileChange(event: any) {
let file = event.target.files[0] let file = event.target.files[0]
this.jsonFile = await this.deployService.readFile(file) this.jsonFile = await this.deployService.readFile(file)
} }
/**
* Appending precode lines to the attached sas or json file for backend deploy
*/
public addPrecodeLines() { public addPrecodeLines() {
let headerLines = [ let headerLines = [
`%let context=${this.selectedContext};`, `%let context=${this.selectedContext};`,
@ -110,6 +125,9 @@ export class ManualComponent implements OnInit {
this.linesOfCode.unshift(...headerLines) this.linesOfCode.unshift(...headerLines)
} }
/**
* Downloadng file with precode included
*/
public downloadSasPrecodeFile() { public downloadSasPrecodeFile() {
let linesAsText = this.linesOfCode.join('\n') let linesAsText = this.linesOfCode.join('\n')
let filename = this.fileName.split('.')[0] let filename = this.fileName.split('.')[0]
@ -117,6 +135,9 @@ export class ManualComponent implements OnInit {
this.downloadFile(linesAsText, filename, 'sas') this.downloadFile(linesAsText, filename, 'sas')
} }
/**
* Used for downloading log and repsonse as a file
*/
public downloadFile( public downloadFile(
content: any, content: any,
filename: string, filename: string,
@ -125,10 +146,17 @@ export class ManualComponent implements OnInit {
this.deployService.downloadFile(content, filename, extension) this.deployService.downloadFile(content, filename, extension)
} }
/**
* Saving dcpath to localstorage
* FIXME: maybe it'snot necessary
*/
public saveDcPath() { public saveDcPath() {
localStorage.setItem('deploy_dc_loc', this.dcPath) localStorage.setItem('deploy_dc_loc', this.dcPath)
} }
/**
* Send sas.json to be executed (deploying backend)
*/
public async executeJson() { public async executeJson() {
this.isSubmittingJson = true this.isSubmittingJson = true
@ -162,6 +190,9 @@ export class ManualComponent implements OnInit {
this.isSubmittingJson = false this.isSubmittingJson = false
} }
/**
* Send sas file to be executed (deploying backend)
*/
public async executeSAS() { public async executeSAS() {
this.executingScript = true this.executingScript = true
this.jobLog = '' this.jobLog = ''
@ -194,6 +225,10 @@ export class ManualComponent implements OnInit {
} }
} }
/**
* Running makedata service
* @param newTab open and run in new tab
*/
public createDatabase(newTab: boolean = true) { public createDatabase(newTab: boolean = true) {
if (newTab) { if (newTab) {
let url = let url =

View File

@ -5,7 +5,6 @@ import { ServerType } from '@sasjs/utils/types/serverType'
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings' import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
import { SASGroup } from 'src/app/models/sas/public-getgroups.model' import { SASGroup } from 'src/app/models/sas/public-getgroups.model'
import { SASjsApiServerInfo } from 'src/app/models/sasjs-api/SASjsApiServerInfo.model' import { SASjsApiServerInfo } from 'src/app/models/sasjs-api/SASjsApiServerInfo.model'
import { HelperService } from 'src/app/services/helper.service'
import { SasService } from 'src/app/services/sas.service' import { SasService } from 'src/app/services/sas.service'
import { SasjsService } from 'src/app/services/sasjs.service' import { SasjsService } from 'src/app/services/sasjs.service'
@ -51,6 +50,9 @@ export class SasjsConfiguratorComponent implements OnInit {
this.getServerInfo() this.getServerInfo()
} }
/**
* Fethes the sasjs server instance info
*/
getServerInfo() { getServerInfo() {
this.sasjsService this.sasjsService
.getServerInfo() .getServerInfo()
@ -59,6 +61,9 @@ export class SasjsConfiguratorComponent implements OnInit {
}) })
} }
/**
* Fetches user groups from the `usernav/usergroupsbymember` service
*/
getUserGroups() { getUserGroups() {
this.loading = true this.loading = true
@ -99,6 +104,9 @@ export class SasjsConfiguratorComponent implements OnInit {
) )
} }
/**
* Creating database
*/
makeData() { makeData() {
// const _debug = "&_debug=131"; //debug on // const _debug = "&_debug=131"; //debug on
const _debug = ' ' //debug off const _debug = ' ' //debug off

View File

@ -4,20 +4,23 @@ import { NgVarDirective } from './ng-var.directive'
import { DragNdropDirective } from './drag-ndrop.directive' import { DragNdropDirective } from './drag-ndrop.directive'
import { FileDropDirective } from './file-drop.directive' import { FileDropDirective } from './file-drop.directive'
import { FileSelectDirective } from './file-select.directive' import { FileSelectDirective } from './file-select.directive'
import { StealFocusDirective } from './steal-focus.directive'
@NgModule({ @NgModule({
declarations: [ declarations: [
NgVarDirective, NgVarDirective,
DragNdropDirective, DragNdropDirective,
FileDropDirective, FileDropDirective,
FileSelectDirective FileSelectDirective,
StealFocusDirective
], ],
imports: [CommonModule], imports: [CommonModule],
exports: [ exports: [
NgVarDirective, NgVarDirective,
DragNdropDirective, DragNdropDirective,
FileDropDirective, FileDropDirective,
FileSelectDirective FileSelectDirective,
StealFocusDirective
] ]
}) })
export class DirectivesModule {} export class DirectivesModule {}

View File

@ -14,7 +14,9 @@ export class DragNdropDirective {
@Output() fileDropped = new EventEmitter<any>() @Output() fileDropped = new EventEmitter<any>()
@Output() fileDraggedOver = new EventEmitter<any>() @Output() fileDraggedOver = new EventEmitter<any>()
// Dragover listener /**
* Dragover listener
*/
@HostListener('dragover', ['$event']) @HostListener('dragover', ['$event'])
onDragOver(event: any) { onDragOver(event: any) {
event.preventDefault() event.preventDefault()
@ -26,7 +28,9 @@ export class DragNdropDirective {
} }
} }
// Dragleave listener /**
* Dragleave listener
*/
@HostListener('dragleave', ['$event']) @HostListener('dragleave', ['$event'])
public onDragLeave(event: any) { public onDragLeave(event: any) {
event.preventDefault() event.preventDefault()
@ -34,7 +38,9 @@ export class DragNdropDirective {
this.fileOver = false this.fileOver = false
} }
// Drop listener /**
* Drop listener
*/
@HostListener('drop', ['$event']) @HostListener('drop', ['$event'])
public ondrop(event: any) { public ondrop(event: any) {
event.preventDefault() event.preventDefault()
@ -48,6 +54,9 @@ export class DragNdropDirective {
} }
} }
/**
* Checks wether dragging element contain files
*/
private containsFiles(event: any) { private containsFiles(event: any) {
if (event && event.dataTransfer && event.dataTransfer.types) { if (event && event.dataTransfer && event.dataTransfer.types) {
for (let i = 0; i < event.dataTransfer.types.length; i++) { for (let i = 0; i < event.dataTransfer.types.length; i++) {

View File

@ -22,6 +22,9 @@ export class FileDropDirective {
this.element = element this.element = element
} }
/**
* Dragging element drop event
*/
@HostListener('drop', ['$event']) @HostListener('drop', ['$event'])
onDrop(event: DragEvent): void { onDrop(event: DragEvent): void {
this._preventAndStop(event) this._preventAndStop(event)
@ -39,6 +42,9 @@ export class FileDropDirective {
this.fileDrop.emit(fileList) this.fileDrop.emit(fileList)
} }
/**
* Dragging element drag over event
*/
@HostListener('dragover', ['$event']) @HostListener('dragover', ['$event'])
onDragOver(event: DragEvent): void { onDragOver(event: DragEvent): void {
this._preventAndStop(event) this._preventAndStop(event)
@ -59,6 +65,10 @@ export class FileDropDirective {
this.fileOver.emit(false) this.fileOver.emit(false)
} }
/**
* Prevent propagation trough elements and stop default behavior
* For particular event
*/
protected _preventAndStop(event: MouseEvent): void { protected _preventAndStop(event: MouseEvent): void {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()

View File

@ -21,6 +21,9 @@ export class FileSelectDirective {
this.element = element this.element = element
} }
/**
* Checks if files exist in the input after input change
*/
isEmptyAfterSelection(): boolean { isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple return !!this.element.nativeElement.attributes.multiple
} }

View File

@ -0,0 +1,17 @@
import { Directive, HostListener } from '@angular/core'
@Directive({
selector: '[appStealFocus]'
})
export class StealFocusDirective {
constructor() {}
/**
* For some reason newest version of Clarity v17.0.1 is stealing focus when
* clicking on the input inside of the clr-tree-view
* This is workaround
*/
@HostListener('click', ['$event']) onClick(event: any) {
event.target.focus()
}
}

View File

@ -1,7 +0,0 @@
export interface RowValidation {
valid: boolean
invalidError: string
rowNumber?: number
colName?: string
value?: string
}

View File

@ -24,8 +24,8 @@
generatedRecordUrl generatedRecordUrl
? 'copy to clipboard' ? 'copy to clipboard'
: generateEditRecordUrlLoading : generateEditRecordUrlLoading
? 'Generating url...' ? 'Generating url...'
: 'Link to this record' : 'Link to this record'
}} }}
</button> </button>
</ng-container> </ng-container>
@ -112,7 +112,7 @@
<div <div
*ngIf=" *ngIf="
['autocomplete'].includes( ['autocomplete', 'autocomplete.custom'].includes(
$any(currentRecordValidator?.getRule(col.key)?.editor) $any(currentRecordValidator?.getRule(col.key)?.editor)
) )
" "
@ -163,7 +163,7 @@
<div <div
*ngIf=" *ngIf="
['autocomplete'].includes( ['autocomplete', 'autocomplete.custom'].includes(
$any(currentRecordValidator?.getRule(col.key)?.editor) $any(currentRecordValidator?.getRule(col.key)?.editor)
) )
" "
@ -277,7 +277,7 @@
<div> <div>
<button <button
type="button" type="button"
class="btn btn-outline focusable" class="btn btn-outline focusable mr-5i"
(click)="currentRecord!.noLinkOption = false; closeRecordEdit()" (click)="currentRecord!.noLinkOption = false; closeRecordEdit()"
> >
Cancel Cancel

View File

@ -38,7 +38,6 @@
app-soft-select { app-soft-select {
display: block; display: block;
width: 224px; width: 224px;
background: #fff;
border: 1px solid #999; border: 1px solid #999;
color: #000; color: #000;
padding: calc(.25rem + 2px) .5rem; padding: calc(.25rem + 2px) .5rem;
@ -49,7 +48,6 @@
input { input {
width: 100%; width: 100%;
border: 0; border: 0;
background-color: #fff;
&:focus { &:focus {
background: none; background: none;
@ -132,7 +130,6 @@
clr-input-container { clr-input-container {
width: 224px; width: 224px;
background: #fff;
border: 1px solid #999; border: 1px solid #999;
color: #000; color: #000;
padding: calc(.25rem + 2px) .5rem; padding: calc(.25rem + 2px) .5rem;

View File

@ -59,6 +59,12 @@ export class EditRecordComponent implements OnInit {
ngOnInit(): void {} ngOnInit(): void {}
/**
* Runs native HOT validator against cell value
* @param cellValidation column rules
* @param cellValue value in the cell that is beign validated
* @returns Promise boolean - wether valid or invalid
*/
async validateRecordCol( async validateRecordCol(
cellValidation: any, cellValidation: any,
cellValue: any cellValue: any
@ -74,6 +80,12 @@ export class EditRecordComponent implements OnInit {
}) })
} }
/**
* Fired when date field in the record change
* Function will parse date and format to string
* @param date picker value
* @param colKey column name (key)
*/
recordDateChange(date: Date, colKey: string) { recordDateChange(date: Date, colKey: string) {
let cellValidation = this.currentRecordValidator?.getRule(colKey) let cellValidation = this.currentRecordValidator?.getRule(colKey)
let format = cellValidation ? cellValidation.dateFormat : '' let format = cellValidation ? cellValidation.dateFormat : ''
@ -82,24 +94,38 @@ export class EditRecordComponent implements OnInit {
this.currentRecord[colKey] = moment(date).format(format) this.currentRecord[colKey] = moment(date).format(format)
} }
isRecordModalInvalid(): boolean { /**
return this.currentRecordInvalidCols.length > 0 * Close edit record modal and apply changes by emitting output event
} */
confirmRecordEdit() { confirmRecordEdit() {
if (this.currentRecordInvalidCols.length < 1) { if (this.currentRecordInvalidCols.length < 1) {
this.onRecordChange.emit(this.currentRecord) this.onRecordChange.emit(this.currentRecord)
} }
} }
/**
* Close edit record modal without applying the changes
*/
closeRecordEdit() { closeRecordEdit() {
this.onRecordEditClose.emit() this.onRecordEditClose.emit()
} }
/**
* Emitting output event when dropdown (autocomplete) input in any col change
* @param colName column name (key)
* @param col column index
*/
onRecordDropdownChange(colName: string, col: number) { onRecordDropdownChange(colName: string, col: number) {
this.onRecordDropdownChanged.emit({ colName, col }) this.onRecordDropdownChanged.emit({ colName, col })
} }
/**
* Emitting output event when input is focused (clicked on) so we can run a `dynamic cell validation`
* Since that bit must be run from the parent component (editor.component)
* Result is then applied in the `cellValidation` variable and automatically updated in this component.
* @param event input event
* @param colName column name (key)
*/
onRecordInputFocus(event: any, colName: number) { onRecordInputFocus(event: any, colName: number) {
this.onRecordInputFocused.emit({ event, colName }) this.onRecordInputFocused.emit({ event, colName })
} }

View File

@ -164,19 +164,28 @@
<div <div
class="card-header clr-row buttonBar headerBar clr-flex-md-row clr-justify-content-center clr-justify-content-lg-end" class="card-header clr-row buttonBar headerBar clr-flex-md-row clr-justify-content-center clr-justify-content-lg-end"
> >
<div *ngIf="tableTrue" class="clr-col-12 clr-col-lg-4 backBtn"> <div
<span class="btn btn-sm" [routerLink]="['/home']"> *ngIf="tableTrue"
<clr-icon shape="caret" dir="left" size="20"></clr-icon>Back to class="clr-col-12 clr-col-md-3 clr-col-lg-4 backBtn"
table selection >
<span
class="btn icon-collapse btn-sm btn-icon btn-dimmed"
[routerLink]="['/home']"
>
<clr-icon shape="caret" dir="left" size="20"></clr-icon>
<span class="text">Back to table selection</span>
</span> </span>
<span (click)="viewboxManager()" class="btn btn-sm viewbox-open"> <span
(click)="viewboxManager()"
class="btn icon-collapse btn-sm btn-icon btn-dimmed viewbox-open"
>
<clr-icon shape="view-cards" size="20"></clr-icon> <clr-icon shape="view-cards" size="20"></clr-icon>
Viewboxes <span class="text">Viewboxes</span>
</span> </span>
</div> </div>
<div <div
class="clr-col-12 clr-col-lg-4 d-flex flex-column align-items-center" class="clr-col-12 clr-col-md-5 clr-col-lg-4 d-flex flex-column align-items-center"
[class.clr-col-lg-12]="!tableTrue" [class.clr-col-lg-12]="!tableTrue"
> >
<h4 <h4
@ -186,24 +195,40 @@
} as libdsParsed" } as libdsParsed"
class="editor-title text-center mt-0-i" class="editor-title text-center mt-0-i"
> >
<clr-icon <clr-tooltip>
(click)="datasetInfo = true" <clr-icon
shape="info-circle" clrTooltipTrigger
class="is-highlight cursor-pointer" (click)="datasetInfo = true"
size="24" shape="info-circle"
></clr-icon> class="is-highlight cursor-pointer"
size="24"
></clr-icon>
<clr-icon <clr-icon
*ngIf="libdsParsed.tableName.includes('-FC')" *ngIf="libdsParsed.tableName.includes('-FC')"
shape="bolt" shape="bolt"
class="color-yellow" class="color-yellow"
></clr-icon> ></clr-icon>
<span clrTooltipTrigger>
{{ libdsParsed.libName }}.<a
class="mr-10 view-table"
[routerLink]="'/view/data/' + libds!"
>{{ libdsParsed.tableName.replace('-FC', '') }}</a
>
</span>
<ng-container *ngIf="this.dsNote && this.dsNote.length > 0">
<clr-tooltip-content
clrPosition="bottom-left"
clrSize="lg"
*clrIfOpen
>
{{ this.dsNote }}
</clr-tooltip-content>
</ng-container>
</clr-tooltip>
{{ libdsParsed.libName }}.<a
class="mr-10"
[routerLink]="'/view/data/' + libds!"
>{{ libdsParsed.tableName.replace('-FC', '') }}</a
>
<ng-container *ngIf="dataSource"> <ng-container *ngIf="dataSource">
<ng-container *ngIf="!zeroFilterRows"> <ng-container *ngIf="!zeroFilterRows">
({{ dataSource.length | thousandSeparator: ',' }} ({{ dataSource.length | thousandSeparator: ',' }}
@ -215,34 +240,37 @@
</ng-container> </ng-container>
</h4> </h4>
</div> </div>
<div *ngIf="tableTrue" class="clr-col-12 clr-col-lg-4 btnCtrl"> <div
*ngIf="tableTrue"
class="clr-col-12 clr-col-md-4 clr-col-lg-4 btnCtrl"
>
<ng-container *ngIf="hotTable.readOnly && !uploadPreview"> <ng-container *ngIf="hotTable.readOnly && !uploadPreview">
<button <button
type="button" type="button"
class="btnView btn btn-sm btn-icon btn-block" class="btnView btn icon-collapse btn-sm btn-icon btn-block btn-dimmed"
(click)="openQb()" (click)="openQb()"
> >
<clr-icon shape="filter"></clr-icon> <clr-icon shape="filter"></clr-icon>
<span>Filter</span> <span class="text">Filter</span>
</button> </button>
<button <button
type="button" type="button"
class="btn btn-sm btn-primary btn-block" class="btn icon-collapse btn-sm btn-primary btn-block"
(click)="editTable()" (click)="editTable()"
> >
<clr-icon shape="note"></clr-icon> <clr-icon shape="note"></clr-icon>
<span>Edit</span> <span class="text">Edit</span>
</button> </button>
<button <button
*ngIf="!columnLevelSecurityFlag" *ngIf="!columnLevelSecurityFlag"
(click)="onShowUploadModal()" (click)="onShowUploadModal()"
type="button" type="button"
class="btn btn-sm btn-success btn-block mr-0" class="btn icon-collapse btn-sm btn-success btn-block mr-0"
> >
<clr-icon shape="upload"></clr-icon> <clr-icon shape="upload"></clr-icon>
<span>Upload</span> <span class="text">Upload</span>
</button> </button>
</ng-container> </ng-container>
@ -280,7 +308,7 @@
licenceState.value.editor_rows_allowed === 1 licenceState.value.editor_rows_allowed === 1
? 'row' ? 'row'
: 'rows' : 'rows'
}}, contact support@datacontroller.io</span }}, contact support&#64;datacontroller.io</span
> >
</clr-tooltip-content> </clr-tooltip-content>
</clr-tooltip> </clr-tooltip>
@ -346,8 +374,8 @@
<ng-container *ngIf="!getdataError"> <ng-container *ngIf="!getdataError">
<span class="spinner"> Loading... </span> <span class="spinner"> Loading... </span>
<div> <div class="mt-10">
<h3>Loading table</h3> <p cds-text="section">Loading table</p>
</div> </div>
</ng-container> </ng-container>
@ -356,8 +384,8 @@
<clr-icon shape="error-standard" class="error-icon"></clr-icon> <clr-icon shape="error-standard" class="error-icon"></clr-icon>
</span> </span>
<div> <div class="mt-10">
<h3>Loading table error</h3> <p cds-text="section">Loading table error</p>
</div> </div>
</ng-container> </ng-container>
</div> </div>
@ -382,6 +410,7 @@
hotId="hotInstance" hotId="hotInstance"
id="hotTable" id="hotTable"
class="edit-hot" class="edit-hot"
className="htDark"
[class.hidden]="hotTable.hidden" [class.hidden]="hotTable.hidden"
[licenseKey]="hotTable.licenseKey" [licenseKey]="hotTable.licenseKey"
> >
@ -417,7 +446,7 @@
licenceState.value.editor_rows_allowed === 1 licenceState.value.editor_rows_allowed === 1
? 'row' ? 'row'
: 'rows' : 'rows'
}}, contact support@datacontroller.io</span }}, contact support&#64;datacontroller.io</span
> >
</clr-tooltip-content> </clr-tooltip-content>
</clr-tooltip> </clr-tooltip>
@ -467,14 +496,18 @@
: 'rows' : 'rows'
}} }}
will be submitted. To remove the restriction, contact will be submitted. To remove the restriction, contact
support@datacontroller.io</span support&#64;datacontroller.io</span
> >
<div *ngIf="tableTrue" class="clr-offset-md-2 clr-col-md-8"> <div *ngIf="tableTrue" class="clr-offset-md-2 clr-col-md-8">
<div class="form-group"> <div class="text-area-full-width">
<label for="formFields_8">Message</label> <label for="formFields_8" class="mb-5 d-block"
>Message</label
>
<textarea <textarea
clrTextarea
[(ngModel)]="message" [(ngModel)]="message"
[disabled]="!validationDone" [disabled]="!validationDone"
tabindex="0"
[value]=" [value]="
!validationDone !validationDone
? 'Please wait while we validate ' + ? 'Please wait while we validate ' +
@ -482,10 +515,9 @@
' cells.' ' cells.'
: '' : ''
" "
class="w-100" class="submit-reason"
type="text" type="text"
id="formFields_8" id="formFields_8"
rows="5"
></textarea> ></textarea>
</div> </div>
<!-- TODO:approvers list --> <!-- TODO:approvers list -->
@ -504,6 +536,7 @@
[disabled]="!validationDone" [disabled]="!validationDone"
type="submit" type="submit"
class="btn btn-sm btn-success-outline m-0" class="btn btn-sm btn-success-outline m-0"
tabindex="0"
(click)="saveTable(hotTable.data)" (click)="saveTable(hotTable.data)"
> >
Submit Submit
@ -512,6 +545,7 @@
id="cancelSubmitBtn" id="cancelSubmitBtn"
type="button" type="button"
class="btn btn-sm btn-outline" class="btn btn-sm btn-outline"
tabindex="0"
(click)="cancelSubmit(); submit = false; validationDone = 0" (click)="cancelSubmit(); submit = false; validationDone = 0"
> >
Cancel Cancel
@ -528,7 +562,7 @@
Due to current licence, only Due to current licence, only
{{ licenceState.value.submit_rows_limit }} rows in a file will {{ licenceState.value.submit_rows_limit }} rows in a file will
be submitted. To remove the restriction, contact be submitted. To remove the restriction, contact
support@datacontroller.io support&#64;datacontroller.io
</p> </p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -830,6 +864,12 @@
</div> </div>
</clr-modal> </clr-modal>
<app-dataset-info [(open)]="datasetInfo" [dsmeta]="dsmeta"></app-dataset-info> <app-dataset-info
[(open)]="datasetInfo"
[dsmeta]="dsmeta"
[versions]="versions"
(rowClicked)="datasetInfoModalRowClicked($event)"
>
</app-dataset-info>
<app-viewboxes [(viewboxModal)]="viewboxes"></app-viewboxes> <app-viewboxes [(viewboxModal)]="viewboxes"></app-viewboxes>

View File

@ -21,12 +21,12 @@ hot-table {
.handsontable tbody th.ht__highlight, .handsontable thead th.ht__highlight { .handsontable tbody th.ht__highlight, .handsontable thead th.ht__highlight {
&.primaryKeyHeaderStyle { &.primaryKeyHeaderStyle {
background: #306b00b0; background-color: #306b00b0 !important;
} }
} }
.primaryKeyHeaderStyle { .primaryKeyHeaderStyle {
background: #306b006e; background-color: #306b006e !important;
} }
th.readonlyCell { th.readonlyCell {
@ -41,6 +41,12 @@ hot-table {
} }
} }
.submit-reason {
min-height: 120px;
max-height: 120px;
height: 120px;
}
.infoBar { .infoBar {
margin-top:14px; margin-top:14px;
background: #495967; background: #495967;
@ -80,8 +86,7 @@ hot-table {
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
align-items: center; align-items: center;
background: #ffffff; background: var(--clr-vertical-nav-bg-color);
background: #f5f6fe;
} }
.error-icon { .error-icon {
@ -214,6 +219,20 @@ hot-table {
width: 150px; width: 150px;
} }
.view-table {
font-size: inherit !important;
}
// When width is smaller remove the text from the buttons
// keep only the icons
@media (max-width: 992px) {
.icon-collapse {
.text {
display: none;
}
}
}
// FIXME // FIXME
// Let's leave it here for a reference if there // Let's leave it here for a reference if there
// is an issue with viewboxes/filter modal overlaying // is an issue with viewboxes/filter modal overlaying

View File

@ -15,7 +15,15 @@ import { Subject, Subscription } from 'rxjs'
import { SasStoreService } from '../services/sas-store.service' import { SasStoreService } from '../services/sas-store.service'
import * as XLSX from '@sheet/crypto' import * as XLSX from '@sheet/crypto'
/**
* Used in combination with buffer
*/
const iconv = require('iconv-lite') const iconv = require('iconv-lite')
/**
* In combination with `iconv` is used for encoding json data captured with sheet js from excel file into a file again
* Which will be send to backend
*/
const Buffer = require('buffer/').Buffer const Buffer = require('buffer/').Buffer
type AOA = any[][] type AOA = any[][]
@ -30,7 +38,8 @@ import { HotTableInterface } from '../models/HotTable.interface'
import { import {
$DataFormats, $DataFormats,
DSMeta, DSMeta,
EditorsGetdataServiceResponse EditorsGetDataServiceResponse,
Version
} from '../models/sas/editors-getdata.model' } from '../models/sas/editors-getdata.model'
import { DataFormat } from '../models/sas/common/DateFormat' import { DataFormat } from '../models/sas/common/DateFormat'
import SheetInfo from '../models/SheetInfo' import SheetInfo from '../models/SheetInfo'
@ -113,6 +122,8 @@ export class EditorComponent implements OnInit, AfterViewInit {
datasetInfo: boolean = false datasetInfo: boolean = false
dsmeta: DSMeta[] = [] dsmeta: DSMeta[] = []
versions: Version[] = []
dsNote = ''
viewboxes: boolean = false viewboxes: boolean = false
@ -374,6 +385,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.setRestrictions() this.setRestrictions()
} }
/**
* Prepare feature restrictions based on licence key
*/
private parseRestrictions() { private parseRestrictions() {
this.restrictions.restrictAddRecord = this.restrictions.restrictAddRecord =
this.licenceState.value.addRecord === false this.licenceState.value.addRecord === false
@ -383,6 +397,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.licenceState.value.fileUpload === false this.licenceState.value.fileUpload === false
} }
/**
* Applying prepared restrictions
* @param overrideRestrictions can be used to apply and override specific restrictions
*/
private setRestrictions(overrideRestrictions?: EditorRestrictions) { private setRestrictions(overrideRestrictions?: EditorRestrictions) {
if (overrideRestrictions) { if (overrideRestrictions) {
this.restrictions = { this.restrictions = {
@ -402,6 +420,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
} }
/**
* Disabling add row button based on wether rows limit is present
*/
private checkRowLimit() { private checkRowLimit() {
if (this.columnLevelSecurityFlag) return if (this.columnLevelSecurityFlag) return
@ -416,12 +437,19 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
} }
/**
* Resetting filter variables
*/
public resetFilter() { public resetFilter() {
if (this.queryFilterCompList.first) { if (this.queryFilterCompList.first) {
this.queryFilterCompList.first.resetFilter() this.queryFilterCompList.first.resetFilter()
} }
} }
/**
* Openning file upload modal
* If feature is locked, `feature locked` modal will be shown
*/
public onShowUploadModal() { public onShowUploadModal() {
if (this.restrictions.restrictFileUpload) { if (this.restrictions.restrictFileUpload) {
this.eventService.showDemoLimitModal('File Upload') this.eventService.showDemoLimitModal('File Upload')
@ -439,6 +467,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
if (!this.uploadPreview) this.showUploadModal = true if (!this.uploadPreview) this.showUploadModal = true
} }
/**
* Called by FileDropDirective
* @param e true if file is dragged over the drop zone
*/
public fileOverBase(e: boolean): void { public fileOverBase(e: boolean): void {
this.hasBaseDropZoneOver = e this.hasBaseDropZoneOver = e
} }
@ -620,6 +652,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
return returnObj return returnObj
} }
/**
* When excel is password protected we will display the password promppt for user to type password in.
* @returns Password user input or undefined if discarded by user
*/
public promptExcelPassword(): Promise<string | undefined> { public promptExcelPassword(): Promise<string | undefined> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.filePasswordModal = true this.filePasswordModal = true
@ -645,6 +681,13 @@ export class EditorComponent implements OnInit, AfterViewInit {
}) })
} }
/**
* Parses attached file, to be uploaded
* If attached file is CSV it will be send to backend straight away
* If attached file is EXCEL it will be displayed in the table, in preview mode
* @param event file drop event
* @param dropped whether it's dropped or added by browse button
*/
public getFileDesc(event: any, dropped: boolean = false) { public getFileDesc(event: any, dropped: boolean = false) {
this.excelUploadState = 'Loading' this.excelUploadState = 'Loading'
this.excelFileParsing = true this.excelFileParsing = true
@ -899,13 +942,30 @@ export class EditorComponent implements OnInit, AfterViewInit {
return row.map((col: any, index: number) => { return row.map((col: any, index: number) => {
if (!col && col !== 0) col = '' if (!col && col !== 0) col = ''
if (isNaN(col)) { /**
col = col.replace(/"/g, '""') * Keeping this for the reference
* Code below used to convert JSON to CSV
* now the XLSX is converting to CSV
*/
// if (isNaN(col)) {
// // Match and replace the double quotes, ignore the first and last char
// // in case they are double quotes already
// col = col.replace(/(?<!^)"(?!$)/g, '""')
if (col.search(/,/g) > -1) { // if (col.search(/,/g) > -1 ||
col = '"' + col + '"' // col.search(/\r|\n/g) > -1
} // ) {
} // // Missing quotes at the end
// if (col.search(/"$/g) < 0) {
// col = col + '"' // So we add them
// }
// // Missing quotes at the start
// if (col.search(/^"/g) < 0) {
// col = '"' + col // So we add them
// }
// }
// }
const colName = this.headerShow[index] const colName = this.headerShow[index]
const colRule = this.dcValidator?.getRule(colName) const colRule = this.dcValidator?.getRule(colName)
@ -920,20 +980,30 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.data = csvArrayData this.data = csvArrayData
let csvContent = csvArrayHeaders.join(',') + '\n' // Apply licence rows limitation if exists, it is only affecting data
// Apply licence rows limitation if exists // which will be send to SAS
csvContent += csvArrayData const strippedCsvArrayData = csvArrayData.slice(
.slice(0, this.licenceState.value.submit_rows_limit) 0,
.map((e) => e.join(',')) this.licenceState.value.submit_rows_limit
.join('\n') )
// To submit to sas service, we need clean version of CSV of file
// attached. XLSX will do the parsing and heavy lifting
// First we create worksheet of json (data we extracted)
let ws = XLSX.utils.json_to_sheet(strippedCsvArrayData, {
skipHeader: true
})
// create CSV to be uploaded from worksheet
let csvContentClean = XLSX.utils.sheet_to_csv(ws)
// Prepend headers
csvContentClean = csvArrayHeaders.join(',') + '\n' + csvContentClean
if (this.encoding === 'WLATIN1') { if (this.encoding === 'WLATIN1') {
let encoded = iconv.decode(Buffer.from(csvContent), 'CP-1252') let encoded = iconv.decode(Buffer.from(csvContentClean), 'CP-1252')
let blob = new Blob([encoded], { type: 'application/csv' }) let blob = new Blob([encoded], { type: 'application/csv' })
let newCSVFile: File = this.blobToFile(blob, this.filename + '.csv') let newCSVFile: File = this.blobToFile(blob, this.filename + '.csv')
this.uploader.addToQueue([newCSVFile]) this.uploader.addToQueue([newCSVFile])
} else { } else {
let blob = new Blob([csvContent], { type: 'application/csv' }) let blob = new Blob([csvContentClean], { type: 'application/csv' })
let newCSVFile: File = this.blobToFile(blob, this.filename + '.csv') let newCSVFile: File = this.blobToFile(blob, this.filename + '.csv')
this.uploader.addToQueue([newCSVFile]) this.uploader.addToQueue([newCSVFile])
} }
@ -1010,6 +1080,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
} }
/**
* Submits attached excel file that is in preview mode
*/
public submitExcel() { public submitExcel() {
if (this.licenceState.value.submit_rows_limit !== Infinity) { if (this.licenceState.value.submit_rows_limit !== Infinity) {
this.submitLimitNotice = true this.submitLimitNotice = true
@ -1019,6 +1092,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.getFile() this.getFile()
} }
/**
* This method will run validations and upload all of the pending files that are in the uploader queue
*/
public getFile() { public getFile() {
if (this.checkInvalid()) { if (this.checkInvalid()) {
this.eventService.showAbortModal(null, 'Invalid values are present.') this.eventService.showAbortModal(null, 'Invalid values are present.')
@ -1091,6 +1167,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
) )
} }
/**
* After excel file is attached and parsed, this function will display it's content in the HOT table in read only mode
*/
public getPendingExcelPreview() { public getPendingExcelPreview() {
this.queryTextSaved = this.queryText this.queryTextSaved = this.queryText
this.queryText = '' this.queryText = ''
@ -1142,46 +1221,12 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.excelFileParsing = false this.excelFileParsing = false
this.excelUploadState = null this.excelUploadState = null
}) })
/**
* This is half validation feature to speed up file upload
* Currently disabled but will leave it here in case it needs to be re-enabled
*/
// this.excelUploadState = 'Validating-DQ'
// this.validateRowsOnPendingExcel(
// async (rowValidation: RowValidation | undefined) => {
// if (rowValidation) {
// this.eventService.showAbortModal(
// 'Excel validation',
// `Please fix the data and re-submit the file. Invalid data details: <br><br> Row: ${rowValidation.rowNumber} <br> Column: ${rowValidation.colName} <br> Reason: <strong>${rowValidation.invalidError}</strong> <br> Invalid value: ${rowValidation.value}`
// )
// this.excelFileParsing = false
// this.excelUploadState = null
// } else {
// this.excelUploadState = 'Validating-HOT'
// hot.updateSettings(
// {
// data: this.dataSource
// },
// false
// )
// hot.render()
// hot.validateCells(() => {
// this.showUploadModal = false
// this.uploadPreview = true
// this.excelFileParsing = false
// this.excelUploadState = null
// })
// }
// }
// )
} }
/**
* Drops the attached excel file
* @param discardData wheter to discard data parsed from the file or to keep it in the table after dropping a attached excel file
*/
public discardPendingExcel(discardData?: boolean) { public discardPendingExcel(discardData?: boolean) {
this.hotInstance.updateSettings({ this.hotInstance.updateSettings({
maxRows: this.licenceState.value.editor_rows_allowed maxRows: this.licenceState.value.editor_rows_allowed
@ -1205,6 +1250,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
} }
/**
* Drops attached excel file, keeps it's data in the DC table
* User can now edit the table and submit. Witout the file present.
*/
public previewTableEditConfirm() { public previewTableEditConfirm() {
this.discardPendingExcel() this.discardPendingExcel()
this.convertToCorrectTypes(this.dataSource) this.convertToCorrectTypes(this.dataSource)
@ -1909,13 +1958,13 @@ export class EditorComponent implements OnInit, AfterViewInit {
if (entry.values.length > 0) { if (entry.values.length > 0) {
hot.setCellMeta(entry.row, entry.col, 'renderer', 'autocomplete') hot.setCellMeta(entry.row, entry.col, 'renderer', 'autocomplete')
hot.setCellMeta(entry.row, entry.col, 'editor', 'autocomplete') hot.setCellMeta(entry.row, entry.col, 'editor', 'autocomplete.custom')
hot.setCellMeta(entry.row, entry.col, 'strict', entry.strict) hot.setCellMeta(entry.row, entry.col, 'strict', entry.strict)
hot.setCellMeta(entry.row, entry.col, 'filter', false) hot.setCellMeta(entry.row, entry.col, 'filter', false)
this.currentEditRecordValidator?.updateRule(entry.col, { this.currentEditRecordValidator?.updateRule(entry.col, {
renderer: 'autocomplete', renderer: 'autocomplete',
editor: 'autocomplete', editor: 'autocomplete.custom',
strict: entry.strict, strict: entry.strict,
filter: false filter: false
}) })
@ -1995,7 +2044,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
(el: DynamicExtendedCellValidation) => (el: DynamicExtendedCellValidation) =>
el.DISPLAY_TYPE === 'C' ? el.RAW_VALUE_CHAR : el.RAW_VALUE_NUM el.DISPLAY_TYPE === 'C' ? el.RAW_VALUE_CHAR : el.RAW_VALUE_NUM
) )
const cellCol = hot.propToCol(cell) const cellCol = hot.propToCol(cell) as number
const dynamicValidationEl = const dynamicValidationEl =
this.disabledBasicDynamicCellValidationMap.find( this.disabledBasicDynamicCellValidationMap.find(
(x) => x.row === row && x.col === cellCol (x) => x.row === row && x.col === cellCol
@ -2010,13 +2059,13 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
hot.setCellMeta(row, cellCol, 'renderer', 'autocomplete') hot.setCellMeta(row, cellCol, 'renderer', 'autocomplete')
hot.setCellMeta(row, cellCol, 'editor', 'autocomplete') hot.setCellMeta(row, cellCol, 'editor', 'autocomplete.custom')
hot.setCellMeta(row, cellCol, 'strict', cellValidationEntry.strict) hot.setCellMeta(row, cellCol, 'strict', cellValidationEntry.strict)
hot.setCellMeta(row, cellCol, 'filter', false) hot.setCellMeta(row, cellCol, 'filter', false)
this.currentEditRecordValidator?.updateRule(cellCol, { this.currentEditRecordValidator?.updateRule(cellCol, {
renderer: 'autocomplete', renderer: 'autocomplete',
editor: 'autocomplete', editor: 'autocomplete.custom',
strict: cellValidationEntry.strict, strict: cellValidationEntry.strict,
filter: false filter: false
}) })
@ -2214,8 +2263,8 @@ export class EditorComponent implements OnInit, AfterViewInit {
setTimeout(() => { setTimeout(() => {
let txt: any = document.getElementById('formFields_8') let txt: any = document.getElementById('formFields_8')
txt.focus() if (txt) txt.focus()
}) }, 200)
}) })
// let cnt = 0; // let cnt = 0;
@ -2659,13 +2708,13 @@ export class EditorComponent implements OnInit, AfterViewInit {
const strict = this.cellValidationSource[validationSourceIndex].strict const strict = this.cellValidationSource[validationSourceIndex].strict
hot.setCellMeta(row, column, 'renderer', 'autocomplete') hot.setCellMeta(row, column, 'renderer', 'autocomplete')
hot.setCellMeta(row, column, 'editor', 'autocomplete') hot.setCellMeta(row, column, 'editor', 'autocomplete.custom')
hot.setCellMeta(row, column, 'strict', strict) hot.setCellMeta(row, column, 'strict', strict)
hot.setCellMeta(row, column, 'filter', false) hot.setCellMeta(row, column, 'filter', false)
this.currentEditRecordValidator?.updateRule(column, { this.currentEditRecordValidator?.updateRule(column, {
renderer: 'autocomplete', renderer: 'autocomplete',
editor: 'autocomplete', editor: 'autocomplete.custom',
strict: strict, strict: strict,
filter: false filter: false
}) })
@ -2717,6 +2766,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
}) })
hot.setCellMeta(row, column, 'renderer', spinnerRenderer) hot.setCellMeta(row, column, 'renderer', spinnerRenderer)
this.currentEditRecordLoadings.push(column) this.currentEditRecordLoadings.push(column)
hot.render() hot.render()
@ -2887,6 +2937,16 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
} }
datasetInfoModalRowClicked(value: Version | DSMeta) {
if ((<Version>value).LOAD_REF !== undefined) {
// Type is Version
const row = value as Version
const url = `/stage/${row.LOAD_REF}`
this.router.navigate([url])
}
}
viewboxManager() { viewboxManager() {
this.viewboxes = true this.viewboxes = true
} }
@ -2899,6 +2959,37 @@ export class EditorComponent implements OnInit, AfterViewInit {
) )
} }
/**
* Function checks if selected hot cell is solo cell selected
* and if it is, set the `filter` property based on filter param.
*
* @param filter
*/
private setCellFilter(filter: boolean) {
const hotSelected = this.hotInstance.getSelected()
const selection = hotSelected ? hotSelected[0] : hotSelected
// When we open a dropdown we want filter disabled so value in cell
// don't filter out items, since we want to see them all.
// But when we start typing we want to be able to start filtering values
// again
if (selection) {
const startRow = selection[0]
const endRow = selection[2]
const startCell = selection[1]
const endCell = selection[3]
if (startRow === endRow && startCell === endCell) {
const cellMeta = this.hotInstance.getCellMeta(startRow, startCell)
// If filter is not already set at the value in the param, set it
if (cellMeta && cellMeta.filter === !filter) {
this.hotInstance.setCellMeta(startRow, startCell, 'filter', filter)
}
}
}
}
async ngOnInit() { async ngOnInit() {
this.licenceService.hot_license_key.subscribe( this.licenceService.hot_license_key.subscribe(
(hot_license_key: string | undefined) => { (hot_license_key: string | undefined) => {
@ -2945,7 +3036,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
await this.sasStoreService await this.sasStoreService
.callService(myParams, 'SASControlTable', 'editors/getdata', this.libds) .callService(myParams, 'SASControlTable', 'editors/getdata', this.libds)
.then((res: EditorsGetdataServiceResponse) => { .then((res: EditorsGetDataServiceResponse) => {
this.initSetup(res) this.initSetup(res)
}) })
.catch((err: any) => { .catch((err: any) => {
@ -2957,7 +3048,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {} ngAfterViewInit() {}
initSetup(response: EditorsGetdataServiceResponse) { initSetup(response: EditorsGetDataServiceResponse) {
this.hotInstance = this.hotRegisterer.getInstance('hotInstance') this.hotInstance = this.hotRegisterer.getInstance('hotInstance')
if (this.getdataError) return if (this.getdataError) return
@ -2966,6 +3057,21 @@ export class EditorComponent implements OnInit, AfterViewInit {
this.cols = response.data.cols this.cols = response.data.cols
this.dsmeta = response.data.dsmeta this.dsmeta = response.data.dsmeta
this.versions = response.data.versions || []
const notes = this.dsmeta.find((item) => item.NAME === 'NOTES')
const longDesc = this.dsmeta.find((item) => item.NAME === 'DD_LONGDESC')
const shortDesc = this.dsmeta.find((item) => item.NAME === 'DD_SHORTDESC')
if (notes && notes.VALUE) {
this.dsNote = notes.VALUE
} else if (longDesc && longDesc.VALUE) {
this.dsNote = longDesc.VALUE
} else if (shortDesc && shortDesc.VALUE) {
this.dsNote = shortDesc.VALUE
} else {
this.dsNote = ''
}
const hot: Handsontable = this.hotInstance const hot: Handsontable = this.hotInstance
@ -3152,6 +3258,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
if (col === 0) { if (col === 0) {
th.classList.add('firstColumnHeaderStyle') th.classList.add('firstColumnHeaderStyle')
} }
// Dark mode
th.classList.add('darkTH')
}, },
afterGetCellMeta: ( afterGetCellMeta: (
row: number, row: number,
@ -3240,28 +3349,16 @@ export class EditorComponent implements OnInit, AfterViewInit {
} }
) )
hot.addHook('beforeKeyDown', (e: any) => { hot.addHook('afterBeginEditing', () => {
const hotSelected = this.hotInstance.getSelected()
const selection = hotSelected ? hotSelected[0] : hotSelected
// When we open a dropdown we want filter disabled so value in cell // When we open a dropdown we want filter disabled so value in cell
// don't filter out items, since we want to see them all. // don't filter out items, since we want to see them all.
this.setCellFilter(false)
})
hot.addHook('beforeKeyDown', () => {
// When we start typing, we are enabling the filter since we want to find // When we start typing, we are enabling the filter since we want to find
// values faster. // values faster.
if (selection) { this.setCellFilter(true)
const startRow = selection[0]
const endRow = selection[2]
const startCell = selection[1]
const endCell = selection[3]
if (startRow === endRow && startCell === endCell) {
const cellMeta = this.hotInstance.getCellMeta(startRow, startCell)
if (cellMeta && cellMeta.filter === false) {
this.hotInstance.setCellMeta(startRow, startCell, 'filter', true)
}
}
}
}) })
hot.addHook('afterChange', (source: any, change: any) => { hot.addHook('afterChange', (source: any, change: any) => {
@ -3270,7 +3367,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
const row = source[0][0] const row = source[0][0]
const colProp = source[0][1] const colProp = source[0][1]
const col = hot.propToCol(colProp) const col = hot.propToCol(colProp) as number
// On edit we enabled filter for this cell, now when editing is finished // On edit we enabled filter for this cell, now when editing is finished
// We want filter to be disabled again, to be ready for next dropdown opening. // We want filter to be disabled again, to be ready for next dropdown opening.

View File

@ -12,7 +12,6 @@ import { EditRecordComponent } from './components/edit-record/edit-record.compon
import { UploadStaterComponent } from './components/upload-stater/upload-stater.component' import { UploadStaterComponent } from './components/upload-stater/upload-stater.component'
import { EditorRoutingModule } from './editor-routing.module' import { EditorRoutingModule } from './editor-routing.module'
import { EditorComponent } from './editor.component' import { EditorComponent } from './editor.component'
import { HomeModule } from '../home/home.module'
import { DcTreeModule } from '../shared/dc-tree/dc-tree.module' import { DcTreeModule } from '../shared/dc-tree/dc-tree.module'
import { DragDropModule } from '@angular/cdk/drag-drop' import { DragDropModule } from '@angular/cdk/drag-drop'
import { ViewboxesModule } from '../shared/viewboxes/viewboxes.module' import { ViewboxesModule } from '../shared/viewboxes/viewboxes.module'
@ -33,7 +32,6 @@ registerAllModules()
AppSharedModule, AppSharedModule,
DirectivesModule, DirectivesModule,
SharedModule, SharedModule,
HomeModule,
PipesModule, PipesModule,
DcTreeModule, DcTreeModule,
DragDropModule, DragDropModule,

View File

@ -1,5 +1,10 @@
import { DcValidation } from 'src/app/shared/dc-validator/models/dc-validation.model' import { DcValidation } from 'src/app/shared/dc-validator/models/dc-validation.model'
/**
* Wrapper for DC Validation because we need `noLinkOption` property
* to be used as a flag to show/hide button that generates link for the
* edit record modal
*/
export interface EditRecordModal extends DcValidation { export interface EditRecordModal extends DcValidation {
noLinkOption: boolean noLinkOption: boolean
[key: string]: any [key: string]: any

View File

@ -1,19 +0,0 @@
export interface CellValidation {
data: string
length: number
type?: string
source: string[]
format?: number
validator?: any
valid?: boolean
renderer?: any
dateFormat?: string
readOnly?: boolean
desc?: string
correctFormat?: boolean
/**
* Key for accessing object fields, any type because it can be
* any of the types interface have
*/
[key: string]: any
}

View File

@ -1,36 +0,0 @@
export enum ColumnType {
string = 'string',
number = 'number'
}
export interface ColumnInterface {
id: number | undefined
name: string | undefined
type: ColumnType | undefined
length: number | undefined
}
export class Column implements ColumnInterface {
public id: number | undefined
public name: string | undefined
public type: ColumnType | undefined
public length: number | undefined
public static fromPlainObject(obj: object) {
return Object.assign(new Column(), obj)
}
constructor(id?: number, name?: string, type?: ColumnType, length?: number) {
this.id = id
this.name = name
this.type = type
this.length = length
}
get hsType() {
return (
(this.type === ColumnType.string && 'text') ||
(this.type === ColumnType.number && 'numeric') ||
null
)
}
}

View File

@ -1,3 +1,7 @@
/**
* Model for the dynamic cell validation in the editor
* (sending whole row to the backend service and recieving data for the cell dropdown)
*/
export interface DynamicExtendedCellValidation { export interface DynamicExtendedCellValidation {
DISPLAY_INDEX: number DISPLAY_INDEX: number
DISPLAY_TYPE: string DISPLAY_TYPE: string

View File

@ -1,8 +1,14 @@
/**
* Edit record modal - input has been focused event
*/
export interface EditRecordInputFocusedEvent { export interface EditRecordInputFocusedEvent {
event: any event: any
colName: number colName: number
} }
/**
* Edit record modal - dropdown has been changed event
*/
export interface EditRecordDropdownChangeEvent { export interface EditRecordDropdownChangeEvent {
colName: string colName: string
col: number col: number

View File

@ -1,3 +1,6 @@
/**
* Editor restrictions model (based on the licencing)
*/
export interface EditorRestrictions { export interface EditorRestrictions {
restrictEditRecord?: boolean // Feature is locked but edit/add record buttons are visible so when user clicks he gets the `locked feature modal` restrictEditRecord?: boolean // Feature is locked but edit/add record buttons are visible so when user clicks he gets the `locked feature modal`
restrictAddRecord?: boolean // Same as editRecord, but for addRecord restrictAddRecord?: boolean // Same as editRecord, but for addRecord

View File

@ -1,71 +0,0 @@
import { Column, ColumnType } from './models/column'
export enum TableType {
INPUT = 'In',
OUTPUT = 'Out'
}
export interface TableInterface {
id: number | undefined
name: string | undefined
data: Array<Object>
columns: Array<Column>
type: TableType | undefined
}
export class Table implements TableInterface {
public id: number | undefined
public name: string | undefined
public data: Array<any>
public columns: Array<Column> = []
public type: TableType | undefined
public static fromPlainObject(obj: any) {
obj.columns = obj.columns.map((column: object) => {
return Column.fromPlainObject(column)
})
return Object.assign(new Table(), obj)
}
constructor(
id?: number,
name?: string,
type?: TableType,
data?: Array<Object>,
columns?: Array<Column>
) {
this.id = id
this.name = name
this.type = type
this.data = data || [{}]
this.columns = columns || []
}
public getNextColumnId(): number {
let highestIdColumn: any = this.columns.sort(
(cA: any, cB: any) => cA.id - cB.id
)[this.columns.length - 1]
return (highestIdColumn && highestIdColumn.id + 1) || 0
}
public addColumn(column: Column) {
this.columns.push(column)
this.data.forEach((row: any) => {
if (column.name) {
row[column.name] = column.type === ColumnType.string ? '' : null
}
})
return column
}
public removeColumn(colInd: any) {
this.data.forEach((row) => {
delete row[this.columns[colInd].name!]
})
this.columns.splice(colInd, 1)
}
}

View File

@ -1,3 +1,6 @@
/**
* Converting date object to the UTC time string
*/
export const dateToUtcTime = (date: Date) => { export const dateToUtcTime = (date: Date) => {
let timeStr = ('0' + date.getUTCHours()).slice(-2) + ':' let timeStr = ('0' + date.getUTCHours()).slice(-2) + ':'
timeStr = timeStr + ('0' + date.getUTCMinutes()).slice(-2) + ':' timeStr = timeStr + ('0' + date.getUTCMinutes()).slice(-2) + ':'
@ -5,6 +8,9 @@ export const dateToUtcTime = (date: Date) => {
return timeStr return timeStr
} }
/**
* Converts date object to the time string
*/
export const dateToTime = (date: Date) => { export const dateToTime = (date: Date) => {
let timeStr = ('0' + date.getHours()).slice(-2) + ':' let timeStr = ('0' + date.getHours()).slice(-2) + ':'
timeStr = timeStr + ('0' + date.getMinutes()).slice(-2) + ':' timeStr = timeStr + ('0' + date.getMinutes()).slice(-2) + ':'
@ -12,6 +18,9 @@ export const dateToTime = (date: Date) => {
return timeStr return timeStr
} }
/**
* Converts date object to the YYYY-MM-DD
*/
export const dateFormat = (date: Date) => { export const dateFormat = (date: Date) => {
return ( return (
date.getFullYear() + date.getFullYear() +

View File

@ -1,9 +1,17 @@
import { Col } from 'src/app/shared/dc-validator/models/col.model' import { Col } from 'src/app/shared/dc-validator/models/col.model'
/**
* Converts excel date serial number to JS date
*/
export const excelDateToJSDate = (serial: number) => { export const excelDateToJSDate = (serial: number) => {
return new Date(Math.round((serial - 25569) * 86400 * 1000)) return new Date(Math.round((serial - 25569) * 86400 * 1000))
} }
/**
* Parsing table columns for the HOT in editor
* Converts array of objects into array of strings, every string is column name (key)
* @param data array of objects (columns data)
*/
export const parseTableColumns = (data: Col[]): string[] => { export const parseTableColumns = (data: Col[]): string[] => {
const columns: string[] = [] const columns: string[] = []
@ -16,6 +24,12 @@ export const parseTableColumns = (data: Col[]): string[] => {
return columns return columns
} }
/**
* Captures headers that are not found in the current table but is found in the uploaded file data
* @param data
* @param headers
* @returns string array of missing headers
*/
export const getMissingHeaders = (data: any, headers: any) => { export const getMissingHeaders = (data: any, headers: any) => {
const missingHeaders: string[] = [] const missingHeaders: string[] = []
const remainingHeaders: string[] = [] const remainingHeaders: string[] = []

View File

@ -1,3 +1,7 @@
/**
* Custom renderer for HOT cell
* Used to show error icon
*/
export const errorRenderer = ( export const errorRenderer = (
instance: any, instance: any,
td: any, td: any,
@ -7,13 +11,19 @@ export const errorRenderer = (
value: any, value: any,
cellProperties: any cellProperties: any
) => { ) => {
addDarkClass(td)
td.innerHTML = `${ td.innerHTML = `${
value ? value.toString() : '' value ? value.toString() : ''
} <clr-icon shape="exclamation-circle" status="warning"></clr-icon>` } <cds-icon shape="exclamation-triangle" status="warning"></cds-icon>`
return td return td
} }
/**
* Custom renderer for HOT cell
* Used to revert cell back to original state (no spinner, no error)
*/
export const noSpinnerRenderer = ( export const noSpinnerRenderer = (
instance: any, instance: any,
td: any, td: any,
@ -23,12 +33,18 @@ export const noSpinnerRenderer = (
value: any, value: any,
cellProperties: any cellProperties: any
) => { ) => {
addDarkClass(td)
td.innerHTML = value ? value : '' td.innerHTML = value ? value : ''
return td return td
} }
// Spinner shown whilst waiting for SAS to respond /**
* Custom renderer for HOT cell
* Used to show loading spinner in the cell
* (Spinner shown whilst waiting for SAS to respond)
*/
export const spinnerRenderer = ( export const spinnerRenderer = (
instance: any, instance: any,
td: any, td: any,
@ -38,9 +54,20 @@ export const spinnerRenderer = (
value: any, value: any,
cellProperties: any cellProperties: any
) => { ) => {
addDarkClass(td)
td.innerHTML = `${ td.innerHTML = `${
value ? value.toString() : '' value ? value.toString() : ''
} <span class="spinner spinner-sm vertical-align-middle"></span>` } <span class="spinner spinner-sm vertical-align-middle"></span>`
return td return td
} }
/**
* Adds a htDark class to a TD element if not existing
*/
const addDarkClass = (td: any) => {
if (!td.classList.contains('htDark')) {
td.classList.add('htDark')
}
}

View File

@ -3,6 +3,7 @@
<clr-tree-node *ngIf="groups" class="search-node"> <clr-tree-node *ngIf="groups" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchLibTreeInput #searchLibTreeInput
placeholder="Filter by Groups" placeholder="Filter by Groups"
@ -27,7 +28,7 @@
<clr-tree-node <clr-tree-node
(click)="groupOnClick(group)" (click)="groupOnClick(group)"
*ngIf="!group['hidden']" *ngIf="!group['hidden']"
[class.table-active]="group.GROUPURI === groupUri" [class.active]="group.GROUPURI === groupUri"
> >
<p class="m-0 cursor-pointer list-padding"> <p class="m-0 cursor-pointer list-padding">
<clr-icon shape="users"></clr-icon> <clr-icon shape="users"></clr-icon>

View File

@ -1,26 +1,63 @@
@import '../../colors.scss';
::ng-deep body[cds-theme="dark"] {
.group-info {
background-color: $headerBackground;
border-color: $headerBackground;
}
.group-data {
background-color: $headerBackground;
border-color: $headerBackground;
}
.member-table tbody{
tr:hover{
background-color: #29404b;
}
}
}
::ng-deep body[cds-theme="light"] {
.group-info{
background-color: #f9f9f9;
border-color: #a7a7a7;
box-shadow: 0px 2px 5px #dad7d7;
}
.group-data {
background-color: #f9f9f9;
border-color: #a7a7a7;
box-shadow: 0px 2px 5px #dad7d7;
}
.member-table tbody{
tr:hover{
background-color: #e6e6e6;
}
}
}
.sidebar-height{ .sidebar-height{
height: 100%; height: 100%;
} }
.group-info-text{ .group-info-text{
display: inline; display: inline;
font-size: 20px; font-size: 20px;
} }
.group-info{ .group-info{
background-color: #f9f9f9; border: 1px solid;
border: 1px solid #a7a7a7;
border-radius: 3px; border-radius: 3px;
box-shadow: 0px 2px 5px #dad7d7;
} }
.group-info td{ .group-info td{
text-align: center; text-align: center;
} }
.group-data{ .group-data{
background-color: #f9f9f9; border: 1px solid;
border: 1px solid #a7a7a7;
border-radius: 3px; border-radius: 3px;
box-shadow: 0px 2px 5px #dad7d7;
} }
.group-data{ .group-data{
min-height: auto; min-height: auto;
h3, h5{ h3, h5{
@ -28,15 +65,11 @@
} }
.member-table{ .member-table{
background-color: #f9f9f9;
width: 100%; width: 100%;
} }
.member-table thead{
background-color: #dadada;
}
.member-table tbody{ .member-table tbody{
tr:hover{ tr:hover{
background-color: #e6e6e6;
cursor: pointer; cursor: pointer;
} }
} }

View File

@ -0,0 +1,23 @@
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { HomeRouteComponent } from '../routes/home-route/home-route.component'
import { HomeComponent } from './home.component'
import { XLMapModule } from '../xlmap/xlmap.module'
const routes: Routes = [
{
path: '',
component: HomeRouteComponent,
children: [
{ path: '', pathMatch: 'full', redirectTo: 'tables' },
{ path: 'tables', component: HomeComponent },
{ path: 'files', loadChildren: () => XLMapModule }
]
}
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomeRoutingModule {}

View File

@ -4,6 +4,7 @@
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
clrInput clrInput
appStealFocus
#searchLibTreeInput #searchLibTreeInput
placeholder="Libraries" placeholder="Libraries"
name="input" name="input"
@ -46,6 +47,7 @@
<clr-tree-node *ngIf="library['tables']" class="search-node"> <clr-tree-node *ngIf="library['tables']" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchTreeInput #searchTreeInput
placeholder="Tables" placeholder="Tables"
@ -85,7 +87,7 @@
(click)="!tableLocked ? onTableClick(libTable, library) : ''" (click)="!tableLocked ? onTableClick(libTable, library) : ''"
class="clr-treenode-link" class="clr-treenode-link"
[class.dc-locked-control]="tableLocked" [class.dc-locked-control]="tableLocked"
[class.table-active]="libTabActive(library.LIBRARYREF, libTable)" [class.active]="libTabActive(library.LIBRARYREF, libTable)"
> >
<ng-container [ngSwitch]="libTable.includes('-FC')"> <ng-container [ngSwitch]="libTable.includes('-FC')">
<clr-icon *ngSwitchCase="true" shape="bolt"></clr-icon> <clr-icon *ngSwitchCase="true" shape="bolt"></clr-icon>
@ -94,15 +96,17 @@
{{ libTable.replace('-FC', '') }} {{ libTable.replace('-FC', '') }}
</button> </button>
<clr-tooltip-content <ng-container *ngIf="tableLocked">
clrPosition="bottom-right" <clr-tooltip-content
clrSize="lg" clrPosition="bottom-right"
*clrIfOpen clrSize="lg"
> *clrIfOpen
<span *ngIf="tableLocked"> >
To unlock all tables, contact support@datacontroller.io <span>
</span> To unlock all tables, contact support&#64;datacontroller.io
</clr-tooltip-content> </span>
</clr-tooltip-content>
</ng-container>
</clr-tooltip> </clr-tooltip>
</clr-tree-node> </clr-tree-node>
</clr-tree-node> </clr-tree-node>
@ -124,12 +128,20 @@
size="60" size="60"
class="is-info icon-dc-fill" class="is-info icon-dc-fill"
></clr-icon> ></clr-icon>
<h3 *ngIf="treeNodeLibraries?.length! > 0" class="text-center color-gray"> <p
*ngIf="treeNodeLibraries?.length! > 0"
class="text-center color-gray mt-10"
cds-text="section"
>
Please select a table Please select a table
</h3> </p>
<h3 *ngIf="treeNodeLibraries?.length! < 1" class="text-center color-gray"> <p
*ngIf="treeNodeLibraries?.length! < 1"
class="text-center color-gray mt-10"
cds-text="section"
>
No Editable Tables Configured No Editable Tables Configured
</h3> </p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,15 +1,18 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common' import { CommonModule } from '@angular/common'
import { HomeComponent } from './home.component' import { NgModule } from '@angular/core'
import { ClarityModule } from '@clr/angular'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { ClarityModule } from '@clr/angular'
import { AppSharedModule } from '../app-shared.module' import { AppSharedModule } from '../app-shared.module'
import { DcTreeModule } from '../shared/dc-tree/dc-tree.module'
import { DirectivesModule } from '../directives/directives.module' import { DirectivesModule } from '../directives/directives.module'
import { HomeRouteComponent } from '../routes/home-route/home-route.component'
import { DcTreeModule } from '../shared/dc-tree/dc-tree.module'
import { HomeRoutingModule } from './home-routing.module'
import { HomeComponent } from './home.component'
@NgModule({ @NgModule({
declarations: [HomeComponent], declarations: [HomeComponent, HomeRouteComponent],
imports: [ imports: [
HomeRoutingModule,
FormsModule, FormsModule,
ClarityModule, ClarityModule,
AppSharedModule, AppSharedModule,

View File

@ -0,0 +1,19 @@
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { LicensingGuard } from '../routes/licensing.guard'
import { LicensingComponent } from './licensing.component'
const routes: Routes = [
{
path: ':action',
component: LicensingComponent,
canActivate: [LicensingGuard],
canDeactivate: [LicensingGuard]
}
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class LicensingRoutingModule {}

View File

@ -2,147 +2,152 @@
<div class="card-header">Licencing</div> <div class="card-header">Licencing</div>
<div [ngSwitch]="action" class="card-block"> <div [ngSwitch]="action" class="card-block">
<ng-container *ngSwitchCase="'key'"> <div class="card-text">
<p class="key-error" *ngIf="!keyError"> <ng-container *ngSwitchCase="'key'">
Licence key is invalid. We can't provide you more details at the moment <p class="key-error" *ngIf="!keyError">
Licence key is invalid. We can't provide you more details at the
moment
</p>
<p
class="key-error"
*ngIf="keyError"
[innerHTML]="licenseErrors[keyError]"
></p>
<p *ngIf="errorDetails"><strong>Details:</strong> {{ errorDetails }}</p>
</ng-container>
<ng-container *ngSwitchCase="'limit'">
<p class="key-error">
The registered number of users reached the limit specified for your
licence. Please contact
<contact-link classes="color-green" />
or your reseller to arrange additional licences for this product.
</p>
</ng-container>
<ng-container *ngSwitchCase="'update'">
<p class="key-error">
Update the license key by uploading the licence file or by pasting a
license key and activation key in the inputs below.
</p>
</ng-container>
<p>
<strong>SYSSITE:</strong>
<span
*ngFor="let id of syssite.value; let i = index"
[class.misskey]="missmatchedKey && missmatchedKey === id"
>
{{ id }}{{ i === syssite.value?.length! - 1 ? '' : ',' }}
</span>
<a
class="tooltip tooltip-md tooltip-top-right"
(click)="copySyssite(copyIcon, copyTooltip, syssite.value || [])"
>
<clr-icon
#copyIcon
class="cursor-pointer"
shape="copy"
size="15"
></clr-icon>
<span #copyTooltip class="tooltip-content">Copy to clipboard</span>
</a>
</p> </p>
<p <p *ngIf="licenseKeyData && userCountLimitation" class="m-0">
class="key-error" <strong>Allowed users:</strong>
*ngIf="keyError" {{ licenseKeyData.users_allowed }}
[innerHTML]="licenseErrors[keyError]"
></p>
<p *ngIf="errorDetails"><strong>Details:</strong> {{ errorDetails }}</p>
</ng-container>
<ng-container *ngSwitchCase="'limit'">
<p class="key-error">
The registered number of users reached the limit specified for your
licence. Please contact
<contact-link classes="color-green" />
or your reseller to arrange additional licences for this product.
</p> </p>
</ng-container>
<ng-container *ngSwitchCase="'update'"> <clr-tabs>
<p class="key-error"> <clr-tab>
Update the license key by uploading the licence file or by pasting a <button clrTabLink>Upload licence</button>
license key and activation key in the inputs below. <clr-tab-content>
</p> <input
</ng-container> #licenceFile
(change)="onFileCapture($event)"
<p> type="file"
<strong>SYSSITE:</strong> hidden
<span />
*ngFor="let id of syssite.value; let i = index" <div
[class.misskey]="missmatchedKey && missmatchedKey === id" (click)="licenceFile.click()"
> appFileDrop
{{ id }}{{ i === syssite.value?.length! - 1 ? '' : ',' }} (fileDrop)="onFileCapture($event, true)"
</span> class="drop-area"
>
<a <clr-spinner
class="tooltip tooltip-md tooltip-top-right" class="spinner-sm"
(click)="copySyssite(copyIcon, copyTooltip, syssite.value || [])" *ngIf="licenceFileLoading"
> ></clr-spinner>
<clr-icon <ng-container *ngIf="!licenceFileLoading">
#copyIcon <div *ngIf="licencefile.filename === ''">
class="cursor-pointer" Drop / Browse licence file
shape="copy" </div>
size="15" <div *ngIf="licencefile.filename !== ''">
></clr-icon> Selected file: <strong>{{ licencefile.filename }}</strong>
<span #copyTooltip class="tooltip-content">Copy to clipboard</span> </div>
</a> <div *ngIf="licenceFileError">
</p> <strong>{{ licenceFileError }}</strong>
</div>
<p *ngIf="licenseKeyData && userCountLimitation" class="m-0"> </ng-container>
<strong>Allowed users:</strong>
{{ licenseKeyData.users_allowed }}
</p>
<clr-tabs>
<clr-tab>
<button clrTabLink>Upload licence</button>
<clr-tab-content>
<input
#licenceFile
(change)="onFileCapture($event)"
type="file"
hidden
/>
<div
(click)="licenceFile.click()"
appFileDrop
(fileDrop)="onFileCapture($event, true)"
class="drop-area"
>
<clr-spinner
class="spinner-sm"
*ngIf="licenceFileLoading"
></clr-spinner>
<ng-container *ngIf="!licenceFileLoading">
<div *ngIf="licencefile.filename === ''">
Drop / Browse licence file
</div>
<div *ngIf="licencefile.filename !== ''">
Selected file: <strong>{{ licencefile.filename }}</strong>
</div>
<div *ngIf="licenceFileError">
<strong>{{ licenceFileError }}</strong>
</div>
</ng-container>
</div>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button clrTabLink>Paste licence</button>
<clr-tab-content>
<form class="clr-form license-key-form">
<p>Licence key:</p>
<div class="clr-control-container">
<textarea
[(ngModel)]="licenceKeyValue"
(mouseleave)="trimKeys()"
name="license-key-area"
placeholder="Paste licence key here"
class="clr-textarea"
></textarea>
</div> </div>
</form> </clr-tab-content>
</clr-tab>
<form class="clr-form activation-key-form"> <clr-tab>
<p>Activation key:</p> <button clrTabLink>Paste licence</button>
<div class="clr-control-container"> <clr-tab-content>
<textarea <form class="clr-form license-key-form">
[(ngModel)]="activationKeyValue" <p>Licence key:</p>
(mouseleave)="trimKeys()" <div class="clr-control-container">
name="activation-key-area" <textarea
placeholder="Paste activation key here" [(ngModel)]="licenceKeyValue"
class="clr-textarea" (mouseleave)="trimKeys()"
></textarea> name="license-key-area"
</div> placeholder="Paste licence key here"
</form> class="clr-textarea"
</clr-tab-content> ></textarea>
</clr-tab> </div>
</clr-tabs> </form>
<button <form class="clr-form activation-key-form">
(click)="applyKeys()" <p>Activation key:</p>
class="btn btn-primary apply-keys" <div class="clr-control-container">
[clrLoading]="applyingKeys" <textarea
[disabled]="disableApplyButton" [(ngModel)]="activationKeyValue"
> (mouseleave)="trimKeys()"
Apply licence keys name="activation-key-area"
</button> placeholder="Paste activation key here"
class="clr-textarea"
></textarea>
</div>
</form>
</clr-tab-content>
</clr-tab>
</clr-tabs>
</div>
<button <div class="card-footer d-flex clr-align-items-center">
*ngIf="isAppFreeTier.value" <button
routerLink="/" (click)="applyKeys()"
class="btn btn-sm btn-link" class="btn btn-primary apply-keys"
> [clrLoading]="applyingKeys"
Continue with free tier [disabled]="disableApplyButton"
</button> >
Apply licence keys
</button>
<button
*ngIf="isAppFreeTier.value"
routerLink="/"
class="btn btn-sm btn-link"
>
Continue with free tier
</button>
</div>
</div> </div>
</div> </div>

View File

@ -33,7 +33,6 @@
.apply-keys { .apply-keys {
height: 40px; height: 40px;
width: 200px;
} }
.drop-area { .drop-area {

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { LicensingRoutingModule } from './licensing-routing.module'
import { ClarityModule } from '@clr/angular'
import { SharedModule } from '../shared/shared.module'
import { LicensingComponent } from './licensing.component'
import { FormsModule } from '@angular/forms'
@NgModule({
declarations: [LicensingComponent],
imports: [
CommonModule,
FormsModule,
ClarityModule,
LicensingRoutingModule,
SharedModule
]
})
export class LicensingModule {}

View File

@ -3,6 +3,7 @@
<clr-tree-node *ngIf="libraryList" class="search-node"> <clr-tree-node *ngIf="libraryList" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchLibTreeInput #searchLibTreeInput
placeholder="Libraries" placeholder="Libraries"
@ -42,6 +43,7 @@
<clr-tree-node *ngIf="library['tables']" class="search-node"> <clr-tree-node *ngIf="library['tables']" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchTreeInput #searchTreeInput
placeholder="Tables" placeholder="Tables"
@ -85,6 +87,7 @@
<clr-tree-node *ngIf="libTable['columns']" class="search-node"> <clr-tree-node *ngIf="libTable['columns']" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchTreeInput #searchTreeInput
placeholder="Columns" placeholder="Columns"
@ -138,7 +141,9 @@
size="60" size="60"
class="is-info icon-dc-fill" class="is-info icon-dc-fill"
></clr-icon> ></clr-icon>
<h3 class="text-center color-gray">Please select a column or table</h3> <p class="text-center color-gray mt-10" cds-text="section">
Please select a column or table
</p>
</div> </div>
<ng-container *ngIf="column || table"> <ng-container *ngIf="column || table">
@ -180,13 +185,13 @@
<button <button
(click)="limitDotDepth = true" (click)="limitDotDepth = true"
type="button" type="button"
class="btn btn-outline" class="btn btn-outline mr-5"
> >
Limit depth Limit depth
</button> </button>
<!-- <button class="btn btn-outline" (click)='showSvg()'> Open in New Tab </button> --> <!-- <button class="btn btn-outline" (click)='showSvg()'> Open in New Tab </button> -->
<div class="btn-group d-block"> <div class="btn-group direction d-block">
<div <div
class="radio btn" class="radio btn"
(click)=" (click)="

View File

@ -1,6 +1,8 @@
@import '../../colors.scss';
.toggle-switch input[type=checkbox]:checked+label:before { .toggle-switch input[type=checkbox]:checked+label:before {
border-color: #314351; border-color: $headerBackground;
background-color: #314351!important; background-color: $headerBackground !important;
transition: .15s ease-in; transition: .15s ease-in;
transition-property: border-color,background-color; transition-property: border-color,background-color;
} }
@ -41,6 +43,10 @@ clr-tree-node button {
white-space: nowrap; white-space: nowrap;
} }
.btn-group.direction {
margin-left: var(--cds-global-space-6);
}
.graph-render-spinner { .graph-render-spinner {
position: absolute; position: absolute;
top: 0; top: 0;

View File

@ -656,11 +656,10 @@ export class LineageComponent {
this.flatdata = res.flatdata this.flatdata = res.flatdata
if (this.libraryList) { if (this.libraryList) {
let libraryToSelect = this.libraryList.find( let libraryToSelect = this.libraryList.find((library: any) =>
(library: any) => res.info[0]?.LIBURI?.toUpperCase()?.includes(
res.info[0]?.LIBURI?.toUpperCase()?.includes( library?.LIBRARYID?.toUpperCase()
library?.LIBRARYID?.toUpperCase() )
)
) )
let tableToSelect: any let tableToSelect: any

View File

@ -22,6 +22,7 @@
<clr-tree-node *ngIf="metaDataList" class="search-node"> <clr-tree-node *ngIf="metaDataList" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchLibTreeInput #searchLibTreeInput
placeholder="search SAS Types" placeholder="search SAS Types"
@ -72,7 +73,9 @@
size="60" size="60"
class="is-info icon-dc-fill" class="is-info icon-dc-fill"
></clr-icon> ></clr-icon>
<h3 class="text-center color-gray">Please select a type</h3> <p class="text-center color-gray mt-10" cds-text="section">
Please select a type
</p>
</div> </div>
<div class="loadingSpinner" *ngIf="loading"> <div class="loadingSpinner" *ngIf="loading">
@ -123,12 +126,18 @@
[class.object-header]="!entry.count" [class.object-header]="!entry.count"
class="full-width" class="full-width"
> >
<clr-icon <div>
*ngIf="!entry.count" <clr-icon
shape="rack-server" *ngIf="!entry.count"
></clr-icon> shape="rack-server"
<clr-icon *ngIf="entry.count" shape="block"></clr-icon> ></clr-icon>
{{ entry.display }} <clr-icon
*ngIf="entry.count"
shape="block"
></clr-icon>
{{ entry.display }}
</div>
<p class="float-right object-uri" *ngIf="!entry.count"> <p class="float-right object-uri" *ngIf="!entry.count">
{{ entry.URI }} {{ entry.URI }}
</p> </p>
@ -163,9 +172,15 @@
[clrExpandable]="true" [clrExpandable]="true"
> >
<div [class.object-header]="!entry.count" class="full-width"> <div [class.object-header]="!entry.count" class="full-width">
<clr-icon *ngIf="!entry.count" shape="rack-server"></clr-icon> <div>
<clr-icon *ngIf="entry.count" shape="block"></clr-icon> <clr-icon
{{ entry.display }} *ngIf="!entry.count"
shape="rack-server"
></clr-icon>
<clr-icon *ngIf="entry.count" shape="block"></clr-icon>
{{ entry.display }}
</div>
<p class="float-right object-uri" *ngIf="!entry.count"> <p class="float-right object-uri" *ngIf="!entry.count">
{{ entry.URI }} {{ entry.URI }}
</p> </p>

View File

@ -1,14 +1,27 @@
::ng-deep body[cds-theme="dark"] {
.object-header:hover {
background-color: #405560;
}
}
::ng-deep body[cds-theme="light"] {
.objects-col {
background: white;
}
.object-header:hover {
background-color: #d8e3e9;
}
}
.objects-col{ .objects-col{
height: 75vh; height: 75vh;
overflow: scroll; overflow: scroll;
border: 1px solid #cccccc; border: 1px solid #cccccc;
background: white;
border-radius: 4px; border-radius: 4px;
} }
.cols-head { .cols-head {
background: #fafafa;
border: 1px solid #cccccc; border: 1px solid #cccccc;
padding: 10px; padding: 10px;
display: flex; display: flex;
@ -40,11 +53,13 @@
margin-top: 5px; margin-top: 5px;
} }
.object-header{ .object-header{
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 3px; padding-left: 3px;
padding-right: 3px; padding-right: 3px;
} }
.object-header:hover{ .object-header:hover{
background-color: #d8e3e9;
border-radius: 3px; border-radius: 3px;
} }
.datagrid-host{ .datagrid-host{

View File

@ -0,0 +1,9 @@
export interface AppSettings {
persistSelectedTheme: boolean
selectedTheme: AppThemes
}
export enum AppThemes {
light = 'light',
dark = 'dark'
}

View File

@ -0,0 +1,5 @@
export interface ErrorBody {
message: string
details: any
raw: any
}

View File

@ -6,6 +6,7 @@ export interface FilterClause {
operators: string[] operators: string[]
type: string type: string
value: any value: any
valueVariable: boolean
values: { formatted: string; unformatted: any }[] values: { formatted: string; unformatted: any }[]
variable: string variable: string
} }

View File

@ -4,12 +4,12 @@ import { DQData, SASParam } from '../TableData'
import { BaseSASResponse } from './common/BaseSASResponse' import { BaseSASResponse } from './common/BaseSASResponse'
import { DataFormat } from './common/DateFormat' import { DataFormat } from './common/DateFormat'
export interface EditorsGetdataServiceResponse { export interface EditorsGetDataServiceResponse {
data: EditorsGetdataSASResponse data: EditorsGetDataSASResponse
libds: string libds: string
} }
export interface EditorsGetdataSASResponse extends BaseSASResponse { export interface EditorsGetDataSASResponse extends BaseSASResponse {
$sasdata: $DataFormats $sasdata: $DataFormats
sasdata: Sasdata[] sasdata: Sasdata[]
sasparams: SASParam[] sasparams: SASParam[]
@ -17,6 +17,7 @@ export interface EditorsGetdataSASResponse extends BaseSASResponse {
dqrules: DQRule[] dqrules: DQRule[]
dsmeta: DSMeta[] dsmeta: DSMeta[]
dqdata: DQData[] dqdata: DQData[]
versions: Version[]
cols: Col[] cols: Col[]
maxvarlengths: Maxvarlength[] maxvarlengths: Maxvarlength[]
xl_rules: any[] xl_rules: any[]
@ -27,6 +28,18 @@ export interface DSMeta {
ODS_TABLE: string ODS_TABLE: string
NAME: string NAME: string
VALUE: string VALUE: string
[key: string]: string
}
export interface Version {
LOAD_REF: string
USER_NM: string
VERSION_DTTM: string
VERSION_DESC: string
CHANGED_RECORDS: number
NEW_RECORDS: number
DELETED_RECORDS: number
[key: string]: string | number
} }
export interface Sasdata { export interface Sasdata {

View File

@ -0,0 +1,9 @@
import { BaseSASResponse } from './common/BaseSASResponse'
export interface EditorsRestoreServiceResponse extends BaseSASResponse {
restore_out: RestoreOut[]
}
export interface RestoreOut {
LOADREF: string
}

View File

@ -143,7 +143,6 @@
(ngModelChange)=" (ngModelChange)="
setVariableOperator(queryIndex, query.operator, clauseIndex) setVariableOperator(queryIndex, query.operator, clauseIndex)
" "
class="mt-2"
clrSelect clrSelect
> >
<option *ngFor="let opr of query.operators">{{ opr }}</option> <option *ngFor="let opr of query.operators">{{ opr }}</option>
@ -413,7 +412,10 @@
> >
<app-soft-select <app-soft-select
label="Value" label="Value"
[secondLabel]="'Variable'"
[emitOnlySelected]="query.valueVariable"
[inputId]="'vals_' + queryIndex + '_' + clauseIndex" [inputId]="'vals_' + queryIndex + '_' + clauseIndex"
(selectedLabelChange)="selectedLabelChange($event, query)"
[(value)]="query.value" [(value)]="query.value"
[enableLoadMore]="query.nobs > query.values.length" [enableLoadMore]="query.nobs > query.values.length"
(onInputEvent)=" (onInputEvent)="
@ -423,9 +425,19 @@
onAutocompleteLoadingMore($event, query.variable, queryIndex, clauseIndex) onAutocompleteLoadingMore($event, query.variable, queryIndex, clauseIndex)
" "
> >
<option [value]="column.unformatted" *ngFor="let column of query.values"> <div *ngIf="!query.valueVariable">
{{ column.formatted.trim() }} <option [value]="column.unformatted" *ngFor="let column of query.values">
</option> {{ column.formatted.trim() }}
</option>
</div>
<div *ngIf="query.valueVariable">
<ng-container *ngFor="let column of cols">
<option [value]="column.NAME" *ngIf="column.TYPE === query.type">
{{ column.NAME }}
</option>
</ng-container>
</div>
</app-soft-select> </app-soft-select>
</ng-template> </ng-template>

View File

@ -1,3 +1,25 @@
::ng-deep {
body[cds-theme="dark"] {
.clause-logic {
background: #192a30;
}
.clause-query {
background: #263e48;
}
}
body[cds-theme="light"] {
.clause-logic {
background: #e9e9e9;
}
.clause-query {
background: #fbf8f8;
}
}
}
.content { .content {
display: flex; display: flex;
@ -9,13 +31,12 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
background: #e9e9e9;
padding: 15px; padding: 15px;
} }
.clause-query { .clause-query {
padding: 30px 0px 20px 20px; padding: 30px 0px 20px 20px;
background: #fbf8f8;
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
@ -220,8 +241,11 @@
vertical-align: middle; vertical-align: middle;
margin: 0; margin: 0;
} }
:not(pre) > code[class*="language-"], pre[class*="language-"] {
background-color: #fbf8f8; ::ng-deep body[cds-theme="dark"] {
.line-numbers {
border-color: #989797 !important;
}
} }
pre[class*="language-"] { pre[class*="language-"] {

View File

@ -95,6 +95,7 @@ export class QueryComponent
variable: null, variable: null,
operator: null, operator: null,
value: null, value: null,
valueVariable: false,
startrow: 0, startrow: 0,
rows: 0, rows: 0,
nobs: 0, nobs: 0,
@ -137,6 +138,11 @@ export class QueryComponent
public whereClause: string | undefined public whereClause: string | undefined
public logicOperators: Array<string> = ['AND', 'OR'] public logicOperators: Array<string> = ['AND', 'OR']
/**
* Temporary values array used in pickers
* because they need particular format to work
* before sending values to backend, values are parsed
*/
public queryDateTime: QueryDateTime[] = [] public queryDateTime: QueryDateTime[] = []
public currentClauseIndex: number = -1 public currentClauseIndex: number = -1
@ -158,6 +164,11 @@ export class QueryComponent
} }
} }
/**
* Gets and sets temporary values selected with DATETIME or TIME picker
* Those values are used for picker to work with format it lieks
* Later before sending values to backend, values are parsed
*/
getQueryDateTime(clauseIndex: number, queryIndex: number): QueryDateTime { getQueryDateTime(clauseIndex: number, queryIndex: number): QueryDateTime {
let existingQueryDateTime = this.queryDateTime.find( let existingQueryDateTime = this.queryDateTime.find(
(x) => x.clauseIndex === clauseIndex && x.queryIndex === queryIndex (x) => x.clauseIndex === clauseIndex && x.queryIndex === queryIndex
@ -178,10 +189,30 @@ export class QueryComponent
return existingQueryDateTime return existingQueryDateTime
} }
/**
* When toggling pickers feature we reset the temp picker values array
*/
usePickersChange() { usePickersChange() {
this.queryDateTime = [] this.queryDateTime = []
if (this.usePickers) {
this.clauses.queryObj.forEach((queryObj: any) => {
queryObj.elements.forEach((element: any) => {
const isDateOrTime = ['DATETIME', 'TIME', 'DATE'].includes(
element.ddtype
)
if (isDateOrTime && element.valueVariable) {
element.value = ''
element.valueVariable = false
}
})
})
}
} }
/**
* Resets all variables used for filtering
*/
public resetFilter() { public resetFilter() {
this.whereString = undefined this.whereString = undefined
this.whereClause = undefined this.whereClause = undefined
@ -210,6 +241,10 @@ export class QueryComponent
this.whereClauseFn(true) this.whereClauseFn(true)
} }
/**
* `Globals` are used to store filtering state (variables) as a caching feature
* until browser reloads
*/
public setToGlobals() { public setToGlobals() {
if (!this.caching) return if (!this.caching) return
@ -233,10 +268,12 @@ export class QueryComponent
get(globals, objPath).filter.libds = this.libds get(globals, objPath).filter.libds = this.libds
} }
get(globals, objPath).filter.clauses = this.clauses get(globals, objPath).filter.clauses = this.clauses
console.log('globals', globals)
} }
/**
* `Globals` are used to store filtering state (variables) as a caching feature
* until browser reloads
*/
public getFromGlobals() { public getFromGlobals() {
if (!this.caching) return if (!this.caching) return
@ -269,6 +306,11 @@ export class QueryComponent
} }
} }
/**
* Sets filtering multiple caluses group logic (and / or)
*
* @param groupLogic to set
*/
public setGroupLogic(groupLogic: any) { public setGroupLogic(groupLogic: any) {
this.groupLogic = groupLogic this.groupLogic = groupLogic
this.clauses.groupLogic = groupLogic this.clauses.groupLogic = groupLogic
@ -721,6 +763,12 @@ export class QueryComponent
) )
} }
public selectedLabelChange(label: string, query: any) {
query.valueVariable = label === 'Variable'
query.value = ''
this.whereClauseFn()
}
public variableInputChange( public variableInputChange(
queryVariable: any, queryVariable: any,
index: number, index: number,
@ -830,17 +878,25 @@ export class QueryComponent
*/ */
public hasInvalidCluase(clauses: any): boolean { public hasInvalidCluase(clauses: any): boolean {
for (let clause of clauses) { for (let clause of clauses) {
clause['invalidClause'] = false
if ( if (
clause.variable === null || clause.value === '' &&
clause.operator === null || !(clause.operator === 'NE' || clause.operator === 'CONTAINS')
clause.value === null || ) {
clause.value === '' clause['invalidClause'] = true
return true
}
if (
clause.variable === null ||
clause.operator === null ||
clause.value === null
) { ) {
clause['invalidClause'] = true clause['invalidClause'] = true
return true return true
} else {
clause['invalidClause'] = false
} }
} }

View File

@ -139,10 +139,7 @@
<div class="card-header p-0"> <div class="card-header p-0">
<div class="clr-row"> <div class="clr-row">
<div class="clr-col-md-4 approvalBack"> <div class="clr-col-md-4 approvalBack">
<span <span class="btn btn-outline m-0" (click)="goToApprovalsList()">
class="btn btn-sm btn-outline m-0"
(click)="goToApprovalsList()"
>
<clr-icon shape="caret" dir="left" size="20"></clr-icon>Back to <clr-icon shape="caret" dir="left" size="20"></clr-icon>Back to
approvals list approvals list
</span> </span>
@ -209,22 +206,22 @@
<div class="d-flex justify-content-center mt-0"> <div class="d-flex justify-content-center mt-0">
<div class="clr-row clr-gap-5 clr-gap-sm-0"> <div class="clr-row clr-gap-5 clr-gap-sm-0">
<button <button
class="btn btn-sm btn-outline text-center mt-5" class="btn btn-sm btn-outline text-center mt-5 mr-5i"
(click)="goToBase(jsParams?.TABLE_NM)" (click)="goToBase(jsParams?.TABLE_NM)"
> >
Go to base table screen View base table
</button> </button>
<button <button
class="btn btn-sm btn-success-outline text-center mt-5" class="btn btn-sm btn-success-outline text-center mt-5 mr-5i"
(click)="getTable(tableId)" (click)="getTable(tableId)"
> >
Go to edited screen View staged data
</button> </button>
<button <button
class="btn btn-sm btn-info-outline text-center mt-5" class="btn btn-sm btn-info-outline text-center mt-5"
(click)="goBack(jsParams?.TABLE_NM)" (click)="goBack(jsParams?.TABLE_NM)"
> >
Go back to editor Edit base table
</button> </button>
</div> </div>
</div> </div>
@ -236,7 +233,7 @@
id="acceptBtn" id="acceptBtn"
[clrLoading]="acceptLoading" [clrLoading]="acceptLoading"
type="submit" type="submit"
class="btn btn-sm btn-success" class="btn btn-sm btn-success mr-5i"
(click)="approveTable()" (click)="approveTable()"
[disabled]=" [disabled]="
!loadingTable || params?.ISAPPROVER === 'NO' || noChanges !loadingTable || params?.ISAPPROVER === 'NO' || noChanges
@ -246,7 +243,7 @@
</button> </button>
<button <button
id="rejectBtn" id="rejectBtn"
class="btn btn-sm btn btn-danger mr-0" class="btn btn-sm btn btn-danger mr-5i"
(click)="rejectOpen = true" (click)="rejectOpen = true"
[disabled]=" [disabled]="
!loadingTable || params?.ISAPPROVER === 'NO' || noChanges !loadingTable || params?.ISAPPROVER === 'NO' || noChanges
@ -287,19 +284,15 @@
> >
<span class="label label-warning"> <span class="label label-warning">
Changed Rows Changed Rows
<span class="badge badge-warning">{{ <span class="badge">{{ lens.updated }}</span>
lens.updated
}}</span>
</span> </span>
<span class="label label-success"> <span class="label label-success">
Added Rows Added Rows
<span class="badge badge-success">{{ lens.new }}</span> <span class="badge">{{ lens.new }}</span>
</span> </span>
<span class="label label-danger"> <span class="label label-danger">
Deleted Rows Deleted Rows
<span class="badge badge-danger">{{ <span class="badge">{{ lens.deleted }}</span>
lens.deleted
}}</span>
</span> </span>
</div> </div>
</div> </div>
@ -314,8 +307,8 @@
class="h-24vh d-flex flex-column justify-content-center align-items-center" class="h-24vh d-flex flex-column justify-content-center align-items-center"
> >
<span class="spinner"> Loading... </span> <span class="spinner"> Loading... </span>
<div *ngIf="!loadingTable"> <div *ngIf="!loadingTable" class="mt-10">
<h3>Loading table</h3> <p cds-text="section">Loading table</p>
</div> </div>
</div> </div>
@ -394,9 +387,9 @@
<div class="card-header"> <div class="card-header">
<div class="clr-row"> <div class="clr-row">
<div class="clr-col-md-4 approvalBack"> <div class="clr-col-md-4 approvalBack">
<span class="btn btn-sm btn-outline" (click)="goToSubmitList()"> <span class="btn btn-outline" (click)="goToSubmitList()">
<clr-icon shape="caret" dir="left" size="20"></clr-icon>Back to <cds-icon shape="angle" direction="left" size="20"></cds-icon
submitted list >Back to submitted list
</span> </span>
</div> </div>
<div class="clr-col-md-4"> <div class="clr-col-md-4">
@ -443,22 +436,22 @@
<div class="d-flex justify-content-center mt-0"> <div class="d-flex justify-content-center mt-0">
<div class="clr-row clr-gap-5 clr-gap-sm-0"> <div class="clr-row clr-gap-5 clr-gap-sm-0">
<button <button
class="btn btn-sm btn-outline text-center mt-5" class="btn btn-sm btn-outline text-center mt-5 mr-5i"
(click)="goToBase(subObj.base)" (click)="goToBase(subObj.base)"
> >
Go to base table screen View base table
</button> </button>
<button <button
class="btn btn-sm btn-success-outline text-center mt-5" class="btn btn-sm btn-success-outline text-center mt-5 mr-5i"
(click)="getTable(subObj.tableId)" (click)="getTable(subObj.tableId)"
> >
Go to edited screen View staged data
</button> </button>
<button <button
class="btn btn-sm btn-info-outline text-center mt-5" class="btn btn-sm btn-info-outline text-center mt-5"
(click)="goBack(subObj.base)" (click)="goBack(subObj.base)"
> >
Go back to editor Edit base table
</button> </button>
</div> </div>
</div> </div>
@ -480,15 +473,15 @@
> >
<span class="label label-warning"> <span class="label label-warning">
Changed Rows Changed Rows
<span class="badge badge-warning">{{ lens.updated }}</span> <span class="badge">{{ lens.updated }}</span>
</span> </span>
<span class="label label-success"> <span class="label label-success">
Added Rows Added Rows
<span class="badge badge-success">{{ lens.new }}</span> <span class="badge">{{ lens.new }}</span>
</span> </span>
<span class="label label-danger"> <span class="label label-danger">
Deleted Rows Deleted Rows
<span class="badge badge-danger">{{ lens.deleted }}</span> <span class="badge">{{ lens.deleted }}</span>
</span> </span>
</div> </div>
</div> </div>
@ -522,8 +515,8 @@
class="h-25vh d-flex flex-column justify-content-center align-items-center" class="h-25vh d-flex flex-column justify-content-center align-items-center"
> >
<span class="spinner"> Loading... </span> <span class="spinner"> Loading... </span>
<div *ngIf="!loadingTable"> <div *ngIf="!loadingTable" class="mt-10">
<h3>Loading table</h3> <p cds-text="section">Loading table</p>
</div> </div>
</div> </div>
<div class="tableCont"> <div class="tableCont">

View File

@ -1,3 +1,5 @@
@import '../../../colors.scss';
.loader { .loader {
display:flex; display:flex;
justify-content: center; justify-content: center;
@ -10,19 +12,48 @@
} }
.addedRow { .addedRow {
background: rgb(146, 208, 154);
border: 1px solid rgba(9, 77, 117, 0.2); border: 1px solid rgba(9, 77, 117, 0.2);
border-radius: 5px; border-radius: 5px;
} }
.deletedRow { .deletedRow {
background: rgb(230, 179, 179);
border: 1px solid rgba(70, 71, 70, 0.2); border: 1px solid rgba(70, 71, 70, 0.2);
border-radius: 5px; border-radius: 5px;
} }
::ng-deep body[cds-theme="dark"] {
table {
.updatedRow {
background: #93971e;
}
.addedRow {
background: rgb(86 153 95);
}
.deletedRow {
background: rgb(138 90 90);
}
}
}
::ng-deep body[cds-theme="light"] {
table {
.updatedRow {
background: #fafda8;
}
.addedRow {
background: rgb(146, 208, 154);
}
.deletedRow {
background: rgb(230, 179, 179);
}
}
}
.updatedRow { .updatedRow {
background: #fafda8;
border: 1px solid rgba(9, 117, 9, 0.2); border: 1px solid rgba(9, 117, 9, 0.2);
border-radius: 5px; border-radius: 5px;
} }
@ -45,7 +76,7 @@ background: rgba(252, 135, 120, 0.4);
font-size: .54167rem; font-size: .54167rem;
font-weight: 400; font-weight: 400;
letter-spacing: normal; letter-spacing: normal;
background: #314351; background: $headerBackground;
border-radius: .125rem; border-radius: .125rem;
color: #f0f1ec;; color: #f0f1ec;;
line-height: .75rem; line-height: .75rem;
@ -68,8 +99,8 @@ background: rgba(252, 135, 120, 0.4);
top: auto; top: auto;
right: auto; right: auto;
content: ""; content: "";
border-left: .25rem solid #314351; border-left: .25rem solid $headerBackground;
border-top: .20833rem solid #314351; border-top: .20833rem solid $headerBackground;
border-right: .25rem solid transparent; border-right: .25rem solid transparent;
border-bottom: .20833rem solid transparent; border-bottom: .20833rem solid transparent;
} }
@ -79,8 +110,8 @@ border: 0px solid;
} }
.toggle-switch input[type=checkbox]:checked+label:before { .toggle-switch input[type=checkbox]:checked+label:before {
border-color: #314351; border-color: $headerBackground;
background-color: #314351!important; background-color: $headerBackground !important;
transition: .15s ease-in; transition: .15s ease-in;
transition-property: border-color,background-color; transition-property: border-color,background-color;
} }
@ -140,7 +171,7 @@ border: 0px solid;
.tooll { .tooll {
position: absolute; position: absolute;
background: #e6b3b3; background: #e6b3b3;
color: #314351; color: $headerBackground;
top: 0px; top: 0px;
height: 36px; height: 36px;
width: 100%; width: 100%;

View File

@ -1,13 +1,13 @@
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { SasStoreService } from '../services/sas-store.service' import { SasStoreService } from '../../services/sas-store.service'
import { Component, AfterViewInit, OnDestroy } from '@angular/core' import { Component, AfterViewInit, OnDestroy } from '@angular/core'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { EventService } from '../services/event.service' import { EventService } from '../../services/event.service'
import { import {
AuditorsPostdataSASResponse, AuditorsPostdataSASResponse,
Param Param
} from '../models/sas/auditors-postdata.model' } from '../../models/sas/auditors-postdata.model'
interface ChangesObj { interface ChangesObj {
ind: any ind: any
@ -89,7 +89,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
} }
public goToApprovalsList() { public goToApprovalsList() {
this.route.navigateByUrl('/approve') this.route.navigateByUrl('/review/approve')
} }
public getTable(tableId: any) { public getTable(tableId: any) {
@ -136,7 +136,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
await this.sasStoreService await this.sasStoreService
.rejecting(rejParams, 'BrowserParams', 'approvers/rejection') .rejecting(rejParams, 'BrowserParams', 'approvers/rejection')
.then((res: any) => { .then((res: any) => {
this.route.navigateByUrl('/history') this.route.navigateByUrl('/review/history')
}) })
.catch((err: any) => { .catch((err: any) => {
this.acceptLoading = false this.acceptLoading = false
@ -156,7 +156,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
await this.sasStoreService await this.sasStoreService
.approveTable(approveParams, 'SASControlTable', 'auditors/postdata') .approveTable(approveParams, 'SASControlTable', 'auditors/postdata')
.then((res: any) => { .then((res: any) => {
this.route.navigateByUrl('/history') this.route.navigateByUrl('/review/history')
}) })
.catch((err: any) => { .catch((err: any) => {
this.acceptLoading = false this.acceptLoading = false
@ -164,7 +164,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
} }
public goToSubmitList() { public goToSubmitList() {
this.route.navigateByUrl('/submitted') this.route.navigateByUrl('/review/submitted')
} }
public async callChangesInfo(tableId: any) { public async callChangesInfo(tableId: any) {

View File

@ -99,19 +99,11 @@
</clr-dg-cell> </clr-dg-cell>
</clr-dg-row> </clr-dg-row>
<clr-dg-footer class="d-flex justify-content-start"> <clr-dg-footer>
<span>items per page</span> <clr-dg-pagination #pagination [clrDgPageSize]="10">
<select [(ngModel)]="itemsNum"> <clr-dg-page-size [clrPageSizeOptions]="[3, 5, 10, 15]"
<option [ngValue]="3">3</option> >Items per page</clr-dg-page-size
<option [ngValue]="5">5</option> >
<option [ngValue]="10">10</option>
<option [ngValue]="15">15</option>
</select>
<clr-dg-pagination
#pagination
[clrDgPageSize]="itemsNum"
class="center"
>
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }} of {{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }} of
{{ pagination.totalItems }} approvals {{ pagination.totalItems }} approvals
</clr-dg-pagination> </clr-dg-pagination>

View File

@ -1,3 +1,5 @@
@import '../../../colors.scss';
.column-center { .column-center {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -13,11 +15,11 @@
} }
.tooltip.tooltip-bottom-left>.tooltip-content, .tooltip .tooltip-content.tooltip-bottom-left { .tooltip.tooltip-bottom-left>.tooltip-content, .tooltip .tooltip-content.tooltip-bottom-left {
background: #314351!important; background: $headerBackground !important;
} }
.tooltip.tooltip-bottom-left>.tooltip-content:before, .tooltip .tooltip-content.tooltip-bottom-left:before { .tooltip.tooltip-bottom-left>.tooltip-content:before, .tooltip .tooltip-content.tooltip-bottom-left:before {
border-right: .25rem solid #314351; border-right: .25rem solid $headerBackground;
border-bottom: .20833rem solid #314351; border-bottom: .20833rem solid $headerBackground;
} }
.noBorder { .noBorder {

View File

@ -1,8 +1,8 @@
import { Component, OnInit, ChangeDetectorRef } from '@angular/core' import { Component, OnInit, ChangeDetectorRef } from '@angular/core'
import { SasStoreService } from '../services/sas-store.service' import { SasStoreService } from '../../services/sas-store.service'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { SasService } from '../services/sas.service' import { SasService } from '../../services/sas.service'
import { EventService } from '../services/event.service' import { EventService } from '../../services/event.service'
interface ApproveData { interface ApproveData {
tableId: string tableId: string
@ -45,7 +45,7 @@ export class ApproveComponent implements OnInit {
if (this.approveList !== undefined) { if (this.approveList !== undefined) {
this.tableId = this.approveList[ind].tableId this.tableId = this.approveList[ind].tableId
this.route.navigateByUrl( this.route.navigateByUrl(
'approve/approveDet/' + this.approveList[ind].tableId 'review/approveDet/' + this.approveList[ind].tableId
) )
} }
} }

View File

@ -72,7 +72,7 @@
> >
To unlock more than To unlock more than
{{ licenceState.value.history_rows_allowed }} records, contact {{ licenceState.value.history_rows_allowed }} records, contact
support@datacontroller.io support&#64;datacontroller.io
</p> </p>
</div> </div>

View File

@ -1,11 +1,13 @@
import { Component, OnInit } from '@angular/core' import { Component, OnInit } from '@angular/core'
import { SasStoreService } from '../services/sas-store.service'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { SasService } from '../services/sas.service'
import { EventService } from '../services/event.service'
import { SASjsConfig } from '@sasjs/adapter' import { SASjsConfig } from '@sasjs/adapter'
import { LicenceService } from '../services/licence.service' import {
LicenceService,
SasStoreService,
EventService,
SasService
} from 'src/app/services'
@Component({ @Component({
selector: 'app-history', selector: 'app-history',

View File

@ -0,0 +1,22 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
import { ApproveComponent } from './approve/approve.component'
import { SubmitterComponent } from './submitter/submitter.component'
import { HistoryComponent } from './history/history.component'
const ROUTES: Routes = [
{ path: 'approve', component: ApproveComponent },
{ path: 'approveDet/:tableId', component: ApproveDetailsComponent },
{ path: 'submitted', component: SubmitterComponent },
{ path: 'submitted/:tableId', component: SubmitterComponent },
{ path: 'history', component: HistoryComponent }
]
@NgModule({
declarations: [],
imports: [CommonModule, RouterModule.forChild(ROUTES)],
exports: [RouterModule]
})
export class ReviewRoutingModule {}

View File

@ -0,0 +1,31 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { ClarityModule } from '@clr/angular'
import { HotTableModule } from '@handsontable/angular'
import { DirectivesModule } from '../directives/directives.module'
import { SharedModule } from '../shared/shared.module'
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
import { ApproveComponent } from './approve/approve.component'
import { ReviewRoutingModule } from './review-routing.module'
import { SubmitterComponent } from './submitter/submitter.component'
import { HistoryComponent } from './history/history.component'
@NgModule({
declarations: [
ApproveComponent,
ApproveDetailsComponent,
SubmitterComponent,
HistoryComponent
],
imports: [
CommonModule,
FormsModule,
ReviewRoutingModule,
ClarityModule,
HotTableModule.forRoot(),
DirectivesModule,
SharedModule
]
})
export class ReviewModule {}

View File

@ -86,19 +86,11 @@
</clr-dg-cell> </clr-dg-cell>
</clr-dg-row> </clr-dg-row>
<clr-dg-footer class="d-flex justify-content-start"> <clr-dg-footer>
<span>items per page</span> <clr-dg-pagination #pagination [clrDgPageSize]="10">
<select [(ngModel)]="itemsNum"> <clr-dg-page-size [clrPageSizeOptions]="[3, 5, 10, 15]"
<option [ngValue]="3">3</option> >Items per page</clr-dg-page-size
<option [ngValue]="5">5</option> >
<option [ngValue]="10">10</option>
<option [ngValue]="15">15</option>
</select>
<clr-dg-pagination
#pagination
[clrDgPageSize]="itemsNum"
class="center"
>
{{ pagination.firstItem + 1 }} - {{ pagination.firstItem + 1 }} -
{{ pagination.lastItem + 1 }} of {{ pagination.lastItem + 1 }} of
{{ pagination.totalItems }} submissions {{ pagination.totalItems }} submissions

View File

@ -1,13 +1,15 @@
@import '../../../colors.scss';
.noBorder { .noBorder {
border-bottom: 1px solid transparent!important; border-bottom: 1px solid transparent!important;
} }
.tooltip.tooltip-bottom-left>.tooltip-content, .tooltip .tooltip-content.tooltip-bottom-left { .tooltip.tooltip-bottom-left>.tooltip-content, .tooltip .tooltip-content.tooltip-bottom-left {
background: #314351!important; background: $headerBackground !important;
} }
.tooltip.tooltip-bottom-left>.tooltip-content:before, .tooltip .tooltip-content.tooltip-bottom-left:before { .tooltip.tooltip-bottom-left>.tooltip-content:before, .tooltip .tooltip-content.tooltip-bottom-left:before {
border-right: .25rem solid #314351; border-right: .25rem solid $headerBackground;
border-bottom: .20833rem solid #314351; border-bottom: .20833rem solid $headerBackground;
} }
.no-submitted-tables { .no-submitted-tables {

View File

@ -1,9 +1,7 @@
import { Component, AfterViewInit, OnInit } from '@angular/core' import { Component, AfterViewInit, OnInit } from '@angular/core'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { SasStoreService } from '../services/sas-store.service'
import { ActivatedRoute, Router } from '@angular/router' import { ActivatedRoute, Router } from '@angular/router'
import { SasService } from '../services/sas.service' import { SasStoreService, EventService, SasService } from '../../services'
import { EventService } from '../services/event.service'
interface SubmitterData { interface SubmitterData {
tableId: string tableId: string
@ -46,7 +44,7 @@ export class SubmitterComponent implements OnInit, AfterViewInit {
} }
public goToDetails(table_id: any) { public goToDetails(table_id: any) {
this.router.navigateByUrl('/submitted/' + table_id) this.router.navigateByUrl('/review/submitted/' + table_id)
} }
public getDetails(sub: any, index: any) { public getDetails(sub: any, index: any) {

View File

@ -3,6 +3,7 @@
<clr-tree-node *ngIf="roles" class="search-node"> <clr-tree-node *ngIf="roles" class="search-node">
<div class="tree-search-wrapper"> <div class="tree-search-wrapper">
<input <input
appStealFocus
clrInput clrInput
#searchLibTreeInput #searchLibTreeInput
placeholder="Filter by Roles" placeholder="Filter by Roles"
@ -26,7 +27,7 @@
<clr-tree-node <clr-tree-node
(click)="roleOnClick(role)" (click)="roleOnClick(role)"
*ngIf="!role['hidden']" *ngIf="!role['hidden']"
[class.table-active]="role.ROLEURI === roleUri" [class.active]="role.ROLEURI === roleUri"
> >
<p class="m-0 cursor-pointer list-padding"> <p class="m-0 cursor-pointer list-padding">
<clr-icon shape="blocks-group"></clr-icon> <clr-icon shape="blocks-group"></clr-icon>

Some files were not shown because too many files have changed in this diff Show More