Compare commits
400 Commits
v6.2.1
...
css-refact
Author | SHA1 | Date | |
---|---|---|---|
2e0c60cc0d | |||
f9decbd366 | |||
1dc69341ca | |||
75ae19fa8e | |||
9de04e9a0c | |||
983f59cd51 | |||
7b5e7ae184 | |||
6e96b1daec | |||
9604661f3b | |||
4bd215491f | |||
6a7dd451b5 | |||
841201adab | |||
e013e62776 | |||
6c171a6394 | |||
a377f6e8d6 | |||
0337318e0b | |||
2844c70f95 | |||
7e11c8f375 | |||
23cbbce964 | |||
c63fcdd465 | |||
82412b2659 | |||
eef3832e40 | |||
63b75a1c61 | |||
d1f0879f0a | |||
36416aab2e | |||
7f3577c3ef | |||
69f883034f | |||
1c56af01d0 | |||
43c0f73c21 | |||
e8cd3d63da | |||
b7f564cb21 | |||
3f5cb1e2de | |||
7d8c0472f0 | |||
b8b516ba77 | |||
83b3d775b6 | |||
aea252ccc6 | |||
d8908f9c7f | |||
95289aa952 | |||
149e318a87 | |||
8657826e60 | |||
a45f5bb3b2 | |||
ae9a91a7a1 | |||
3638bde633 | |||
3a2361f42c | |||
1bd0eef913 | |||
85aa3b38b7 | |||
678859a68d | |||
e531acee3f | |||
4a45ebfe3b | |||
8fb9a344f2 | |||
8829b60220 | |||
4e64f28732 | |||
a0749de700 | |||
f9623e046e | |||
bce1fd57ef | |||
c6a1c53b46 | |||
e36229e4c4 | |||
853c1bc23e | |||
3b6f6853bc | |||
b415437662 | |||
24df878abe | |||
f474673a14 | |||
c53ab85107 | |||
5c4dd7c9e3 | |||
217220ffaa | |||
c89a3049fa | |||
bb12bff9db | |||
30d5e51d0b | |||
cd3bcc0ee3 | |||
ef1ba824c3 | |||
bc45e92138 | |||
c2f36f5419 | |||
31a31612fc | |||
f9c2491ab6 | |||
3de095fe77 | |||
e4e04a193f | |||
a1a90519c5 | |||
522979835c | |||
fe049256b5 | |||
31d1870198 | |||
6edf0dfb31 | |||
3bf3dceaa2 | |||
ce503653cd | |||
caa9854ff0 | |||
20c3a338c5 | |||
6547461637 | |||
bbb725c64c | |||
403d08c86a | |||
f66d9f511a | |||
dd2138ac5e | |||
74e9979c67 | |||
ddc22e5200 | |||
4218da91cd | |||
857b94f44f | |||
a3ce367950 | |||
75dac54591 | |||
a156c0111b | |||
e5d93fd7d6 | |||
67436f4ff9 | |||
b712f851a2 | |||
e2c0b8da86 | |||
1b4560061d | |||
d94df7f0eb | |||
fa04d7bf4e | |||
4d4cabb465 | |||
d4fee791a7 | |||
82c285e348 | |||
4d276657b3 | |||
cffeab813d | |||
18363bbbeb | |||
6df7d8d2ba | |||
5deba44d2b | |||
0a8b1e764c | |||
fc52e8f41a | |||
efcdc694dd | |||
eb7c44333c | |||
3c62ff6913 | |||
f4f589af94 | |||
3521579dea | |||
e97a6f52da | |||
3584aa35c7 | |||
b553520abe | |||
e32d44b1bc | |||
105da1503f | |||
29298072e5 | |||
154c10fee5 | |||
7853f7cb6a | |||
e54ecc8a35 | |||
d8b95c5739 | |||
2f8d0b764a | |||
d7732ed206 | |||
6e631cd9a5 | |||
0a9e5dd834 | |||
d14a4eaadd | |||
5f7c7fcc7b | |||
978f152ab6 | |||
68a2a606f3 | |||
bad43135d7 | |||
110ad9a6e9 | |||
e98f288302 | |||
9a79f37bf1 | |||
85909cfc1e | |||
4330da520f | |||
27907ed00f | |||
31c90f3190 | |||
35844e0cf1 | |||
afa7e380aa | |||
cb9a5f0eb4 | |||
da522c557d | |||
2c0afd0268 | |||
20255c69c2 | |||
74f1c5416b | |||
feed7f1ded | |||
967698e4ce | |||
71bd81ae47 | |||
89a5153bb3 | |||
c11bd9a2c5 | |||
59d46a9926 | |||
39c3e5411f | |||
aad419c55d | |||
ee58fd5b4b | |||
5564aea9c2 | |||
aedd2c451b | |||
6d597611b6 | |||
9ffe5efe5d | |||
2715950d86 | |||
77a7190f4d | |||
cc65890fea | |||
93758efb27 | |||
c0dc9191e3 | |||
485783a782 | |||
ee07bef2b8 | |||
0de8481314 | |||
ec0f539a33 | |||
173ee2daff | |||
5c0091b5e8 | |||
84dce7f6e8 | |||
e8a943a35a | |||
b3171a8125 | |||
d77f2eb674 | |||
5474fad9cc | |||
3dd85cc60b | |||
510e412ff2 | |||
3dfdccbc6b | |||
a55661548a | |||
69363b37e9 | |||
2d6a753921 | |||
dc989e5668 | |||
227ac480d5 | |||
c5e4650327 | |||
56cf271e77 | |||
fa8396f039 | |||
904ca30f91 | |||
549f35766b | |||
1589c799ec | |||
604c2e70bd | |||
297a84d3a4 | |||
aaad9f7207 | |||
a4028562ce | |||
5ab3f98855 | |||
eba21e96b4 | |||
9ad7ae47b5 | |||
cf54e4c8f3 | |||
57aa6fa0fc | |||
4a01f3d490 | |||
80a0db951d | |||
3202cb8e08 | |||
ddf36230bf | |||
b67c2be968 | |||
dc2c8da92b | |||
5d6c3701d0 | |||
b024e263b4 | |||
b706864e40 | |||
60cc666b67 | |||
efff4dd553 | |||
2b1dad8e48 | |||
8c7de5aad7 | |||
1db8bc2573 | |||
c60dd65a16 | |||
f7f59a4b0a | |||
ec7615e7e3 | |||
f411c33754 | |||
79121168e4 | |||
ef81e33f70 | |||
96066c66cb | |||
b1819b776d | |||
bd7a392ffc | |||
7997b77158 | |||
d1966bcdc5 | |||
7b5bbe024d | |||
4d84f15aca | |||
928937daab | |||
3bd8d247e5 | |||
cf6c9dd5f2 | |||
ff55cbbaad | |||
3eda4e2c58 | |||
02a8a1c565 | |||
8769841f08 | |||
7208fe1c3b | |||
801c8c6a9f | |||
51ebd25aa3 | |||
c6595c1f61 | |||
a267666e99 | |||
b27fea5b91 | |||
f8a14d4bde | |||
633e35338d | |||
8003da94e6 | |||
c3af97ef57 | |||
31d4e5c727 | |||
fbbcf90956 | |||
f522038b8d | |||
ace599b39f | |||
963562621d | |||
5171d07441 | |||
9a0b9573d5 | |||
4733311ef3 | |||
432450a15b | |||
47638becc0 | |||
bdd3a95685 | |||
38601346a5 | |||
dc3a6ae6a1 | |||
f668b1e7f7 | |||
eb1c09d790 | |||
9bf324c74b | |||
f13e909478 | |||
6a0fe287dd | |||
5a48f2e6e3 | |||
6565834ad4 | |||
837821fd01 | |||
cff5989559 | |||
60510a4d68 | |||
2b54034973 | |||
347b0f9065 | |||
eac0104d7a | |||
1c8e4604de | |||
e9624635ed | |||
f9beda1ddb | |||
53400de110 | |||
cf37ddab22 | |||
625af199f4 | |||
56e9217f4b | |||
86f1af7926 | |||
7737f8455d | |||
b0f1677fcc | |||
4406e0d4b4 | |||
cf19381060 | |||
802d8a3b08 | |||
2a852496e9 | |||
4653097225 | |||
8afee29e02 | |||
233eca39ef | |||
1a96bb1233 | |||
93702c63dc | |||
df065562d1 | |||
802c99adf9 | |||
482c7455f5 | |||
731b96dccc | |||
9550ae4d11 | |||
2d6e747db9 | |||
fd94945466 | |||
d3b0c09332 | |||
01915a2db9 | |||
51b043b6d2 | |||
c144fd8087 | |||
12b15df78c | |||
d6ecd12cea | |||
1c3d498da6 | |||
d75e10aef5 | |||
f0f9d85558 | |||
86f3411896 | |||
6daef39268 | |||
7d1720a360 | |||
b11a4884b4 | |||
50696bb926 | |||
d67d4e2f86 | |||
2f01c4d251 | |||
9ffa30ab74 | |||
5d93346b52 | |||
39762b36c6 | |||
e40ebdff05 | |||
8d12d9e51e | |||
23708c9aae | |||
c86fba9dc7 | |||
e747e6e4e7 | |||
5aec024242 | |||
b473b198a6 | |||
516e5a2062 | |||
fb3abbe491 | |||
3e009f3037 | |||
e63d304953 | |||
3cd90c2d47 | |||
a485c3b787 | |||
2702bb3c84 | |||
56264ecc69 | |||
cc4535245c | |||
6ae31de1dd | |||
2d4d068413 | |||
271543a446 | |||
8f796aec36 | |||
6eb1aa85d2 | |||
ac59b77ad5 | |||
3efccc4cf3 | |||
8cbcd18f4b | |||
6bb2378790 | |||
e7d0ffe8c0 | |||
ab89600c73 | |||
830e3816a0 | |||
dadac4f13f | |||
1de48a49af | |||
687a1e1cb5 | |||
665a04f5c5 | |||
fdb18d242b | |||
ec173da4ce | |||
bb35cc15d2 | |||
181f52eaea | |||
fc7c8101ed | |||
a347603fe0 | |||
09022c995f | |||
3609943f30 | |||
a1d308ea07 | |||
5579db0eaf | |||
3a3e488b23 | |||
0a82ec0a70 | |||
bc1d89218e | |||
817b9adeac | |||
a7aa42a59b | |||
34f239036d | |||
91f128c2fe | |||
a00ebea692 | |||
c27cdab3fc | |||
d7da2d7890 | |||
76f0fd4232 | |||
008b45ad17 | |||
4d49263816 | |||
6a2482e5c6 | |||
b5c3fb2af4 | |||
fa2c8eb839 | |||
f3e82b4ee2 | |||
ba67248155 | |||
a6d962bfaa | |||
95cddb52d4 | |||
5a5118d775 | |||
1b1cdd7a4b | |||
a9ddf7f7dd | |||
b54b3f1778 | |||
349a63c591 | |||
293d33912f | |||
357b9849e7 | |||
0c8a9eef32 | |||
112b1d0da4 | |||
a05007416a | |||
9f7dd55583 | |||
11b06f6416 | |||
adb7eb7755 | |||
b776b80728 | |||
73a149ea7b | |||
ef8784093b | |||
b30c788e3d | |||
23899bdff3 | |||
8bd0dd22c2 |
@ -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,8 +25,117 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NPMRC: ${{ secrets.NPMRC}}
|
NPMRC: ${{ secrets.NPMRC}}
|
||||||
|
|
||||||
- run: npm run lint:check
|
- name: Lint check
|
||||||
- run: |
|
run: npm run lint:check
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
cd client
|
cd client
|
||||||
|
# Decrypt and Install sheet
|
||||||
|
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
|
||||||
npm ci
|
npm ci
|
||||||
|
|
||||||
|
- name: Licence checker
|
||||||
|
run: |
|
||||||
|
cd client
|
||||||
npm run license-checker
|
npm run license-checker
|
||||||
|
|
||||||
|
- name: Angular Tests
|
||||||
|
run: |
|
||||||
|
cd client
|
||||||
|
npm run test:headless
|
||||||
|
|
||||||
|
- name: Production Build
|
||||||
|
run: |
|
||||||
|
cd client
|
||||||
|
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-multi-load.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/csv.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
|
||||||
|
@ -1,224 +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
|
|
||||||
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: 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
|
|
@ -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-multi-load.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/csv.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,18 +176,32 @@ 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
|
||||||
@ -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: |
|
||||||
@ -100,12 +261,18 @@ jobs:
|
|||||||
npm run compodoc:build
|
npm run compodoc:build
|
||||||
surfer put --token ${{ secrets.TSDOC_TOKEN }} --server webdoc.datacontroller.io documentation/* /
|
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
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,9 @@ client/cypress/screenshots
|
|||||||
client/cypress/results
|
client/cypress/results
|
||||||
client/cypress/videos
|
client/cypress/videos
|
||||||
client/documentation
|
client/documentation
|
||||||
|
client/**/sheet-crypto.tgz
|
||||||
|
client/.nx
|
||||||
|
client/libraries/sheet-crypto.tgz
|
||||||
cypress.env.json
|
cypress.env.json
|
||||||
sasjsbuild
|
sasjsbuild
|
||||||
sasjsresults
|
sasjsresults
|
||||||
|
@ -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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@ -1,18 +1,19 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"Licence",
|
||||||
"SYSERRORTEXT",
|
"SYSERRORTEXT",
|
||||||
"SYSWARNINGTEXT"
|
"SYSWARNINGTEXT",
|
||||||
],
|
"xlmaprules",
|
||||||
"editor.rulers": [
|
"xlmaps"
|
||||||
80
|
|
||||||
],
|
],
|
||||||
|
"editor.rulers": [80],
|
||||||
"files.trimTrailingWhitespace": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"[markdown]": {
|
"[markdown]": {
|
||||||
"files.trimTrailingWhitespace": false
|
"files.trimTrailingWhitespace": false
|
||||||
},
|
},
|
||||||
"workbench.colorCustomizations": {
|
"workbench.colorCustomizations": {
|
||||||
"titleBar.activeForeground": "#ebe8e8",
|
"titleBar.activeForeground": "#ebe8e8",
|
||||||
"titleBar.activeBackground": "#95ff0053",
|
"titleBar.activeBackground": "#95ff0053"
|
||||||
},
|
},
|
||||||
"terminal.integrated.wordSeparators": " ()[]{}',\"`─‘’"
|
"terminal.integrated.wordSeparators": " ()[]{}',\"`─‘’"
|
||||||
}
|
}
|
418
CHANGELOG.md
418
CHANGELOG.md
@ -1,3 +1,421 @@
|
|||||||
|
## [6.14.7](https://git.datacontroller.io/dc/dc/compare/v6.14.6...v6.14.7) (2025-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* updated hot, clarity and improved accessibility score. ([2844c70](https://git.datacontroller.io/dc/dc/commit/2844c70f9507036216b8b621900c2bb9010c1d34))
|
||||||
|
|
||||||
|
## [6.14.6](https://git.datacontroller.io/dc/dc/compare/v6.14.5...v6.14.6) (2025-04-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* history table modal links styling ([c63fcdd](https://git.datacontroller.io/dc/dc/commit/c63fcdd465950ada439d7d69622a3886e8f3a783))
|
||||||
|
|
||||||
|
## [6.14.5](https://git.datacontroller.io/dc/dc/compare/v6.14.4...v6.14.5) (2025-03-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* improving accessibility lighthouse score ([7f3577c](https://git.datacontroller.io/dc/dc/commit/7f3577c3ef9f44e55a58bc64fbf89a3a64006dd4))
|
||||||
|
* prevent errors when using sqlrc in a DI job in a HOOK ([d1f0879](https://git.datacontroller.io/dc/dc/commit/d1f0879f0acf7e816c80f7635fd02f4f284214ed))
|
||||||
|
* user profile style fix, new select library and table icons ([69f8830](https://git.datacontroller.io/dc/dc/commit/69f883034fabbed31aa5d832e20561c4ae3042db))
|
||||||
|
|
||||||
|
## [6.14.4](https://git.datacontroller.io/dc/dc/compare/v6.14.3...v6.14.4) (2025-03-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* removing cli dependency warnings2 ([43c0f73](https://git.datacontroller.io/dc/dc/commit/43c0f73c2189ff762986a964caae6b0b108164fc))
|
||||||
|
|
||||||
|
## [6.14.3](https://git.datacontroller.io/dc/dc/compare/v6.14.2...v6.14.3) (2025-03-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* NLDAT & NLDATM formats are now being staged ([3f5cb1e](https://git.datacontroller.io/dc/dc/commit/3f5cb1e2defe390220e904e4bf04a165cb31fec4))
|
||||||
|
|
||||||
|
## [6.14.2](https://git.datacontroller.io/dc/dc/compare/v6.14.1...v6.14.2) (2025-03-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* improving instructions for setup ([83b3d77](https://git.datacontroller.io/dc/dc/commit/83b3d775b6e33653b087ca9f4eb3ad5b0dbbd479))
|
||||||
|
|
||||||
|
## [6.14.1](https://git.datacontroller.io/dc/dc/compare/v6.14.0...v6.14.1) (2025-03-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* handle national language datetime formats ([149e318](https://git.datacontroller.io/dc/dc/commit/149e318a8787be0109f25aeec3a1270ea75a97b2))
|
||||||
|
* updating logic to use NLDAT formats ([95289aa](https://git.datacontroller.io/dc/dc/commit/95289aa9524d3cb2b1c248cfb84f6b0d0a490c32))
|
||||||
|
|
||||||
|
# [6.14.0](https://git.datacontroller.io/dc/dc/compare/v6.13.2...v6.14.0) (2025-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* uses SORTSEQ=LINGUISTIC for the services/metanav/metadetails service ([a45f5bb](https://git.datacontroller.io/dc/dc/commit/a45f5bb3b27a86da5f55ff28c9c7669956484ddf))
|
||||||
|
|
||||||
|
## [6.13.2](https://git.datacontroller.io/dc/dc/compare/v6.13.1...v6.13.2) (2025-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* get metadata email if exists ([1bd0eef](https://git.datacontroller.io/dc/dc/commit/1bd0eef913593579771c647d80010ce628c00819))
|
||||||
|
|
||||||
|
## [6.13.1](https://git.datacontroller.io/dc/dc/compare/v6.13.0...v6.13.1) (2025-02-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Avoiding LATIN1 unprintables in various UI locations ([bce1fd5](https://git.datacontroller.io/dc/dc/commit/bce1fd57ef397cfdd030552c3f424a8407174729))
|
||||||
|
* updated @sasjs/adapter, crypto-browserify ([4e64f28](https://git.datacontroller.io/dc/dc/commit/4e64f28732868b07ec2ab403912bd384c62c7e1d))
|
||||||
|
|
||||||
|
# [6.13.0](https://git.datacontroller.io/dc/dc/compare/v6.12.3...v6.13.0) (2025-01-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* editor page csv upload ([217220f](https://git.datacontroller.io/dc/dc/commit/217220ffaaf688133321cc68d770aaf1e50590a9))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* csv test ([c53ab85](https://git.datacontroller.io/dc/dc/commit/c53ab85107f10c023117a099cc06321afc3e1f03))
|
||||||
|
|
||||||
|
## [6.12.3](https://git.datacontroller.io/dc/dc/compare/v6.12.2...v6.12.3) (2025-01-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* adding missing=STRING to three services ([30d5e51](https://git.datacontroller.io/dc/dc/commit/30d5e51d0b9cf27774038476bd90559600952304))
|
||||||
|
|
||||||
|
## [6.12.2](https://git.datacontroller.io/dc/dc/compare/v6.12.1...v6.12.2) (2025-01-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* unnecessary zeros when adding new row (data schema default values) ([a1a9051](https://git.datacontroller.io/dc/dc/commit/a1a90519c535ca25e00822b4d3358c991ac9662e))
|
||||||
|
|
||||||
|
## [6.12.1](https://git.datacontroller.io/dc/dc/compare/v6.12.0...v6.12.1) (2024-12-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* no upcase of pk fields in MPE_TABLES in delete scenario ([3de095f](https://git.datacontroller.io/dc/dc/commit/3de095fe7797cde60f0e232c188305fe423c27eb)), closes [#134](https://git.datacontroller.io/dc/dc/issues/134)
|
||||||
|
* reduce length of tmp table names. Closes [#130](https://git.datacontroller.io/dc/dc/issues/130) ([f9c2491](https://git.datacontroller.io/dc/dc/commit/f9c2491ab6e7b528b7ffc011fd9e45c963c5f6bf))
|
||||||
|
|
||||||
|
# [6.12.0](https://git.datacontroller.io/dc/dc/compare/v6.11.1...v6.12.0) (2024-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* added appLoc to the system page ([dd2138a](https://git.datacontroller.io/dc/dc/commit/dd2138ac5e6067de310e83d16fccc9b9764ba3ff))
|
||||||
|
* bumping core for passthrough fix, [#124](https://git.datacontroller.io/dc/dc/issues/124) ([caa9854](https://git.datacontroller.io/dc/dc/commit/caa9854ff0431ccbb6ff1d6d3509dc877362cceb))
|
||||||
|
* excel with password flow, introducing web worker for XLSX.read ([a3ce367](https://git.datacontroller.io/dc/dc/commit/a3ce36795007a4e3b6ac3499ffd119dc3758f387))
|
||||||
|
* implemented the new request wrapper usage, added XLSX read with a Web Worker, multi load preview data, full height ([4218da9](https://git.datacontroller.io/dc/dc/commit/4218da91cd193aa45346ad7e34ccc00ca89df4fb))
|
||||||
|
* **multi load:** xlsx read file ahead of time, while user choose datasets ([6547461](https://git.datacontroller.io/dc/dc/commit/65474616379e1dacc1329b3bdc5eb14f34428bb1))
|
||||||
|
* refactored adapter request wrapper function to return job log as well ([67436f4](https://git.datacontroller.io/dc/dc/commit/67436f4ff9bb4d77d5f897f47a3e3d472981f275))
|
||||||
|
* using temporary names for temporary tables ([ce50365](https://git.datacontroller.io/dc/dc/commit/ce503653cd9fc36f72fb172bd14816e07c792e14)), closes [#124](https://git.datacontroller.io/dc/dc/issues/124)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* searching data in excel files using new algorithm (massive performance improvement) ([bbb725c](https://git.datacontroller.io/dc/dc/commit/bbb725c64cc23ed701b189623992408c42fdde8f))
|
||||||
|
|
||||||
|
## [6.11.1](https://git.datacontroller.io/dc/dc/compare/v6.11.0...v6.11.1) (2024-07-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* adding SYSSITE, part of [#116](https://git.datacontroller.io/dc/dc/issues/116) ([a156c01](https://git.datacontroller.io/dc/dc/commit/a156c0111b3de5e3744e38d377d6e9aa09915803))
|
||||||
|
* ensuring review_reason_txt in output. Closes [#117](https://git.datacontroller.io/dc/dc/issues/117) ([e5d93fd](https://git.datacontroller.io/dc/dc/commit/e5d93fd7d6d86bc47ff56664bd812b4d9d0749a5))
|
||||||
|
|
||||||
|
# [6.11.0](https://git.datacontroller.io/dc/dc/compare/v6.10.1...v6.11.0) (2024-06-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* addressing PR comments ([d94df7f](https://git.datacontroller.io/dc/dc/commit/d94df7f0ebae8feab5e1d5cf8011af8c8be2ca18))
|
||||||
|
* **multi load:** fixed parsing algorithm reused for the multi load, the fix affects the normal upload as well. ([d4fee79](https://git.datacontroller.io/dc/dc/commit/d4fee791a72021e449cf9680c3e3a525dce41ac1))
|
||||||
|
* **multi load:** label rename ([fa04d7b](https://git.datacontroller.io/dc/dc/commit/fa04d7bf4e5ba337146bdaa926c60488f8851449))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **multi load:** added HOT for user datasets input ([18363bb](https://git.datacontroller.io/dc/dc/commit/18363bbbeb9cf96183ba4841da8134b2f66f735c))
|
||||||
|
* **multi load:** implemented matching libds and parsing of the multiple sheets ([efcdc69](https://git.datacontroller.io/dc/dc/commit/efcdc694dd275cdb9a4e19f26e5522b8dadc5fd9))
|
||||||
|
* **multi load:** licence submit limits ([cffeab8](https://git.datacontroller.io/dc/dc/commit/cffeab813d8d4b324f82710dfd73953d4cbf8ffe))
|
||||||
|
* **multi load:** multiple csv files ([4d27665](https://git.datacontroller.io/dc/dc/commit/4d276657b35a147a2233a03afcb1716348555f52))
|
||||||
|
* **multi load:** refactored range find function, unlocking excel with password is reusable ([eb7c443](https://git.datacontroller.io/dc/dc/commit/eb7c44333c865e7f7bbfb54dd7f73bfc110f86a7))
|
||||||
|
* **multi load:** submitting multiple found tables at once ([5deba44](https://git.datacontroller.io/dc/dc/commit/5deba44d2b7352866d821b70dbbfbbf54955dc47))
|
||||||
|
|
||||||
|
## [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](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
|
||||||
|
|
||||||
|
* 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)
|
## [6.2.1](https://git.datacontroller.io/dc/dc/compare/v6.2.0...v6.2.1) (2023-10-09)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -28,3 +28,5 @@ 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)!
|
@ -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,9 +68,9 @@
|
|||||||
"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"
|
||||||
]
|
],
|
||||||
|
"webWorkerTsConfig": "tsconfig.worker.json"
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
@ -116,10 +117,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,31 +128,29 @@
|
|||||||
"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"
|
||||||
],
|
],
|
||||||
"karmaConfig": "karma.conf.js"
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"karmaConfig": "karma.conf.js",
|
||||||
|
"webWorkerTsConfig": "tsconfig.worker.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
|
@ -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,
|
||||||
|
115
client/cypress/e2e/csv.cy.ts
Normal file
115
client/cypress/e2e/csv.cy.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { Callbacks } from 'cypress/types/jquery/index'
|
||||||
|
|
||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'csvs/'
|
||||||
|
|
||||||
|
context('excel tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
|
||||||
|
colorLog(
|
||||||
|
`TEST START ---> ${
|
||||||
|
Cypress.mocha.getRunner().suite.ctx.currentTest.title
|
||||||
|
}`,
|
||||||
|
'#3498DB'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Uploads regular csv file', () => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular.csv', () => {
|
||||||
|
cy.get('#approval-btn', { timeout: 60000 })
|
||||||
|
.should('be.visible')
|
||||||
|
// .then(() => {
|
||||||
|
// cy.get('#hotInstance', { timeout: 30000 })
|
||||||
|
// .find('div.ht_master.handsontable')
|
||||||
|
// .find('div.wtHolder')
|
||||||
|
// .find('div.wtHider')
|
||||||
|
// .find('div.wtSpreader')
|
||||||
|
// .find('table.htCore')
|
||||||
|
// .find('tbody')
|
||||||
|
// .then((data) => {
|
||||||
|
// let cell: any = data[0].children[0].children[1]
|
||||||
|
// expect(cell.innerText).to.equal('0')
|
||||||
|
// cell = data[0].children[0].children[2]
|
||||||
|
// expect(cell.innerText).to.equal('44')
|
||||||
|
// cell = data[0].children[0].children[3]
|
||||||
|
// expect(cell.innerText).to.equal('abc')
|
||||||
|
// cell = data[0].children[0].children[6]
|
||||||
|
// expect(cell.innerText).to.equal('Option abc')
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
colorLog(`TEST END -------------`, '#3498DB')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container > button').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||||
|
cy.get('.buttonBar button:last-child')
|
||||||
|
.should('exist')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('input[type="file"]#file-upload')
|
||||||
|
.attachFile(`/${fixturePath}/${excelFilename}`)
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorLog = (msg: string, color: string) => {
|
||||||
|
console.log('%c' + msg, 'color:' + color + ';font-weight:bold;')
|
||||||
|
}
|
@ -15,9 +15,6 @@ context('editor tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -118,10 +115,6 @@ context('editor tests: ', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const clickOnEdit = (callback?: any) => {
|
const clickOnEdit = (callback?: any) => {
|
||||||
@ -221,13 +214,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
|
||||||
|
228
client/cypress/e2e/excel-multi-load.cy.ts
Normal file
228
client/cypress/e2e/excel-multi-load.cy.ts
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
import { Callbacks } from 'cypress/types/jquery/index'
|
||||||
|
|
||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels_multi_load/'
|
||||||
|
|
||||||
|
const library = 'DC996664'
|
||||||
|
const mpeXTestTable = 'MPE_X_TEST'
|
||||||
|
const mpeTablesTable = 'MPE_TABLES'
|
||||||
|
|
||||||
|
context('excel multi load tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
|
visitPage('home/multi-load')
|
||||||
|
|
||||||
|
colorLog(
|
||||||
|
`TEST START ---> ${
|
||||||
|
Cypress.mocha.getRunner().suite.ctx.currentTest.title
|
||||||
|
}`,
|
||||||
|
'#3498DB'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Uploads Excel file with multiple sheets, 3 sheets including data, 2 sheets matched with dataset', (done) => {
|
||||||
|
attachExcelFile('multi_load_test_2.xlsx', () => {
|
||||||
|
checkHotUserDatasetTable('hotTableUserDataset', [
|
||||||
|
[library, mpeXTestTable],
|
||||||
|
[library, mpeTablesTable]
|
||||||
|
], () => {
|
||||||
|
cy.get('#continue-btn').trigger('click').then(() => {
|
||||||
|
checkIfTreeHasTables([`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`], undefined, (includes: boolean) => {
|
||||||
|
if (includes) {
|
||||||
|
// MPE_TABLES sheet does not have data so 1 error image must be shown
|
||||||
|
hasErrorTables(1, (valid: boolean) => {
|
||||||
|
if (valid) done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | Uploads Excel file with multiple sheets, 2 sheets matched with dataset, 1 matched sheet does not have data', (done) => {
|
||||||
|
attachExcelFile('multi_load_test_1.xlsx', () => {
|
||||||
|
checkHotUserDatasetTable('hotTableUserDataset', [
|
||||||
|
[library, mpeXTestTable],
|
||||||
|
[library, mpeTablesTable]
|
||||||
|
], () => {
|
||||||
|
cy.get('#continue-btn').trigger('click').then(() => {
|
||||||
|
checkIfTreeHasTables([`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`], `${library}.${mpeXTestTable}`, (includes: boolean) => {
|
||||||
|
if (includes) {
|
||||||
|
cy.get('#hotTable').should('be.visible').then(() => {
|
||||||
|
checkHotUserDatasetTable('hotTable', [
|
||||||
|
['No', '1', 'more dummy data'],
|
||||||
|
['No', '1', 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'],
|
||||||
|
['No', '1', 'if you can fill the unforgiving minute']
|
||||||
|
], () => {
|
||||||
|
submitTables()
|
||||||
|
|
||||||
|
hasSuccessSubmits(2, (valid: boolean) => {
|
||||||
|
if (valid) done()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | Uploads Excel file with multiple sheets, 1 sheets has 2 tables', (done) => {
|
||||||
|
attachExcelFile('multi_load_test_1.xlsx', () => {
|
||||||
|
checkHotUserDatasetTable('hotTableUserDataset', [
|
||||||
|
[library, mpeXTestTable],
|
||||||
|
[library, mpeTablesTable]
|
||||||
|
], () => {
|
||||||
|
cy.get('#continue-btn').trigger('click').then(() => {
|
||||||
|
checkIfTreeHasTables([`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`], `${library}.${mpeXTestTable}`, (includes: boolean) => {
|
||||||
|
if (includes) {
|
||||||
|
cy.get('#hotTable').should('be.visible').then(() => {
|
||||||
|
checkHotUserDatasetTable('hotTable', [
|
||||||
|
['No', '1', 'more dummy data'],
|
||||||
|
['No', '1', 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'],
|
||||||
|
['No', '1', 'if you can fill the unforgiving minute']
|
||||||
|
], () => {
|
||||||
|
clickOnTreeNode('DC996664.MPE_TABLES', () => {
|
||||||
|
cy.wait(1000).then(() => {
|
||||||
|
cy.get('#hotTable').should('be.visible').then(() => {
|
||||||
|
checkHotUserDatasetTable('hotTable', [
|
||||||
|
['No', 'DC914286', 'MPE_COLUMN_LEVEL_SECURITY'],
|
||||||
|
['No', 'DC914286', 'MPE_XLMAP_INFO'],
|
||||||
|
['No', 'DC914286', 'MPE_XLMAP_RULES']
|
||||||
|
], () => {
|
||||||
|
submitTables()
|
||||||
|
|
||||||
|
hasSuccessSubmits(2, (valid: boolean) => {
|
||||||
|
if (valid) done()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
colorLog(`TEST END -------------`, '#3498DB')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||||
|
cy.get('#browse-file')
|
||||||
|
.should('exist')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('input[type="file"]#file-upload')
|
||||||
|
.attachFile(`/${fixturePath}/${excelFilename}`)
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkHotUserDatasetTable = (hotId: string, dataToContain: any[][], callback?: () => void) => {
|
||||||
|
cy.get(`#${hotId}`, { timeout: longerCommandTimeout })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data) => {
|
||||||
|
cy.wait(2000).then(() => {
|
||||||
|
for (let rowI = 0; rowI < dataToContain.length; rowI++) {
|
||||||
|
for (let colI = 0; colI < dataToContain[rowI].length; colI++) {
|
||||||
|
expect(data[0].children[rowI].children[colI]).to.contain(dataToContain[rowI][colI])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickOnTreeNode = (clickOnNode: string, callback?: () => void) => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => {
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toUpperCase().trim().includes(clickOnNode)) {
|
||||||
|
cy.get(node).trigger('click')
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkIfTreeHasTables = (tables: string[], clickOnNode?: string, callback?: (includes: boolean) => void) => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => {
|
||||||
|
let datasets = tables
|
||||||
|
let nodesCorrect = true
|
||||||
|
let nodeToClick
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (!datasets.includes(node.innerText.toUpperCase().trim())) {
|
||||||
|
nodesCorrect = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickOnNode) {
|
||||||
|
if (node.innerText.toUpperCase().trim().includes(clickOnNode)) {
|
||||||
|
nodeToClick = node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeToClick) {
|
||||||
|
cy.wait(1000)
|
||||||
|
cy.get(nodeToClick).trigger('click')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) callback(nodesCorrect)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitTables = () => {
|
||||||
|
cy.get('#submit-all').trigger('click')
|
||||||
|
cy.get('#submit-tables').trigger('click')
|
||||||
|
cy.wait(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasSuccessSubmits = (expectedNoOfSubmits: number, callback: (valid: boolean) => void) => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="success"]').should('be.visible').then(($nodes) => {
|
||||||
|
callback(expectedNoOfSubmits === $nodes.length)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasErrorTables = (expectedNoOfErrors: number, callback: (valid: boolean) => void) => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="danger"]').should('be.visible').then(($nodes) => {
|
||||||
|
callback(expectedNoOfErrors === $nodes.length)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorLog = (msg: string, color: string) => {
|
||||||
|
console.log('%c' + msg, 'color:' + color + ';font-weight:bold;')
|
||||||
|
}
|
@ -17,9 +17,6 @@ context('excel tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
|
|
||||||
@ -112,13 +109,8 @@ context('excel tests: ', function () {
|
|||||||
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
attachExcelFile('duplicate_column_excel.xlsx', () => {
|
attachExcelFile('duplicate_column_excel.xlsx', () => {
|
||||||
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
submitExcel()
|
||||||
.should('exist')
|
rejectExcel(done)
|
||||||
.then((elements: any) => {
|
|
||||||
if (elements[0]) {
|
|
||||||
if (elements[0].innerText.toLowerCase().includes('missing')) done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -337,7 +329,6 @@ context('excel tests: ', function () {
|
|||||||
|
|
||||||
this.afterEach(() => {
|
this.afterEach(() => {
|
||||||
colorLog(`TEST END -------------`, '#3498DB')
|
colorLog(`TEST END -------------`, '#3498DB')
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -405,13 +396,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 +429,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
|
||||||
|
@ -15,9 +15,7 @@ context('filtering tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation, { timeout: longerCommandTimeout })
|
cy.visit(hostUrl + appLocation, { timeout: longerCommandTimeout })
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -159,24 +157,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(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkInfoBarIncludes = (text: string, callback: any) => {
|
const checkInfoBarIncludes = (text: string, callback: any) => {
|
||||||
|
@ -23,15 +23,12 @@ interface EditConfigTableCells {
|
|||||||
|
|
||||||
context('licensing tests: ', function () {
|
context('licensing tests: ', function () {
|
||||||
this.beforeAll(() => {
|
this.beforeAll(() => {
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
cy.loginAndUpdateValidKey()
|
cy.loginAndUpdateValidKey()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -375,9 +372,7 @@ context('licensing tests: ', function () {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const logout = (callback?: any) => {
|
const logout = (callback?: any) => {
|
||||||
@ -699,13 +694,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
|
||||||
|
@ -18,9 +18,6 @@ context('liveness tests: ', function () {
|
|||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -125,13 +122,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
|
||||||
|
@ -16,7 +16,6 @@ context('editor tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
cy.wait(2000)
|
cy.wait(2000)
|
||||||
|
|
||||||
cy.get('body').then(($body) => {
|
cy.get('body').then(($body) => {
|
||||||
@ -393,10 +392,6 @@ context('editor tests: ', function () {
|
|||||||
// }
|
// }
|
||||||
// )
|
// )
|
||||||
// })
|
// })
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const removeAllColumns = () => {
|
const removeAllColumns = () => {
|
||||||
|
497
client/cypress/fixtures/csvs/regular.csv
Normal file
497
client/cypress/fixtures/csvs/regular.csv
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
PRIMARY_KEY_FIELD,SOME_CHAR,SOME_DROPDOWN,SOME_NUM,SOME_DATE,SOME_DATETIME,SOME_TIME,SOME_SHORTNUM,SOME_BESTNUM
|
||||||
|
0,abc,Option abc,42,12FEB1960,01JAN1960:00:00:42,0:00:42,3,44
|
||||||
|
1,more dummy data,Option 2,42,12FEB1960,01JAN1960:00:00:42,0:07:02,3,44
|
||||||
|
2,even more dummy data,Option 3,42,12FEB1960,01JAN1960:00:00:42,0:02:22,3,44
|
||||||
|
3,"It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:",Option 2,1613.001,27FEB1961,01JAN1960:00:07:03,0:00:44,3,44
|
||||||
|
4,if you can fill the unforgiving minute,Option 1,1613.0011235,02AUG1971,29MAY1973:06:12:03,0:06:52,3,44
|
||||||
|
1010,10 bottles of beer on the wall,Option 1,0.9153696885,04MAR1962,01JAN1960:12:47:55,0:01:40,92,76
|
||||||
|
1011,11 bottles of beer on the wall,Option 1,0.3531217558,29MAR1960,01JAN1960:03:33:24,0:01:03,80,29
|
||||||
|
1012,12 bottles of beer on the wall,Option 1,0.6743748717,02AUG1962,01JAN1960:07:25:59,0:00:10,16,98
|
||||||
|
1013,13 bottles of beer on the wall,Option 1,0.1305445992,11SEP1960,01JAN1960:13:51:32,0:00:35,73,15
|
||||||
|
1014,14 bottles of beer on the wall,Option 1,0.7409067949,26JUL1960,01JAN1960:05:18:10,0:00:41,30,89
|
||||||
|
1015,15 bottles of beer on the wall,Option 1,0.0869016028,28FEB1961,01JAN1960:13:23:45,0:00:44,80,3
|
||||||
|
1016,16 bottles of beer on the wall,Option 1,0.0462121419,09AUG1962,01JAN1960:07:42:38,0:01:17,62,2
|
||||||
|
1017,17 bottles of beer on the wall,Option 1,0.7501918947,14MAY1962,01JAN1960:04:40:20,0:00:15,53,65
|
||||||
|
1018,18 bottles of beer on the wall,Option 1,0.7300173294,03AUG1962,01JAN1960:03:20:41,0:00:41,21,60
|
||||||
|
1019,19 bottles of beer on the wall,Option 1,0.6960950437,01JUN1960,01JAN1960:01:58:52,0:01:08,38,5
|
||||||
|
1020,20 bottles of beer on the wall,Option 1,0.6190566065,30MAY1961,01JAN1960:09:04:20,0:01:07,92,23
|
||||||
|
1021,21 bottles of beer on the wall,Option 1,0.5173368238,07JAN1961,01JAN1960:07:52:34,0:00:52,57,21
|
||||||
|
1022,22 bottles of beer on the wall,Option 1,0.4720626452,07NOV1960,01JAN1960:12:12:00,0:00:26,53,32
|
||||||
|
1023,23 bottles of beer on the wall,Option 1,0.2856596393,08AUG1960,01JAN1960:06:09:25,0:00:28,40,12
|
||||||
|
1024,24 bottles of beer on the wall,Option 1,0.5160869418,02JUN1960,01JAN1960:06:36:06,0:01:10,41,81
|
||||||
|
1025,25 bottles of beer on the wall,Option 1,0.1683158517,05JAN1961,01JAN1960:08:14:35,0:00:06,18,53
|
||||||
|
1026,26 bottles of beer on the wall,Option 1,0.8951142248,28NOV1961,01JAN1960:03:31:17,0:00:58,79,54
|
||||||
|
1027,27 bottles of beer on the wall,Option 1,0.7037817481,01SEP1961,01JAN1960:05:48:34,0:00:29,50,15
|
||||||
|
1028,28 bottles of beer on the wall,Option 1,0.6193826714,31MAR1962,01JAN1960:02:49:39,0:00:24,78,87
|
||||||
|
1029,29 bottles of beer on the wall,Option 1,0.9339028457,06DEC1961,01JAN1960:02:57:57,0:00:24,73,64
|
||||||
|
1030,30 bottles of beer on the wall,Option 1,0.5647351339,10AUG1960,01JAN1960:11:02:59,0:00:55,39,28
|
||||||
|
1031,31 bottles of beer on the wall,Option 1,0.1218988607,19JUN1961,01JAN1960:04:19:32,0:00:58,51,32
|
||||||
|
1032,32 bottles of beer on the wall,Option 1,0.3459929113,14MAY1962,01JAN1960:05:42:48,0:00:54,96,46
|
||||||
|
1033,33 bottles of beer on the wall,Option 1,0.092664999,31AUG1962,01JAN1960:00:08:34,0:00:51,69,90
|
||||||
|
1034,34 bottles of beer on the wall,Option 1,0.9793458097,08FEB1960,01JAN1960:01:55:23,0:00:42,45,28
|
||||||
|
1035,35 bottles of beer on the wall,Option 1,0.8964386624,18DEC1961,01JAN1960:04:42:45,0:00:07,49,97
|
||||||
|
1036,36 bottles of beer on the wall,Option 1,0.0961652911,13NOV1960,01JAN1960:03:44:53,0:01:25,62,59
|
||||||
|
1037,37 bottles of beer on the wall,Option 1,0.3475089201,16JAN1962,01JAN1960:01:35:19,0:00:15,23,50
|
||||||
|
1038,38 bottles of beer on the wall,Option 1,0.3096271312,21MAY1960,01JAN1960:09:51:33,0:00:15,2,71
|
||||||
|
1039,39 bottles of beer on the wall,Option 1,0.9445223114,28AUG1962,01JAN1960:07:09:31,0:00:12,30,31
|
||||||
|
1040,40 bottles of beer on the wall,Option 1,0.5626084667,06NOV1960,01JAN1960:01:42:16,0:01:14,18,97
|
||||||
|
1041,41 bottles of beer on the wall,Option 1,0.9432962513,01JUN1962,01JAN1960:03:30:04,0:00:11,20,34
|
||||||
|
1042,42 bottles of beer on the wall,Option 1,0.5802429382,08JUL1961,01JAN1960:08:12:43,0:01:26,18,5
|
||||||
|
1043,43 bottles of beer on the wall,Option 1,0.1970176255,27MAR1961,01JAN1960:00:19:45,0:01:29,13,76
|
||||||
|
1044,44 bottles of beer on the wall,Option 1,0.4980671608,05JAN1961,01JAN1960:13:36:08,0:00:56,4,36
|
||||||
|
1045,45 bottles of beer on the wall,Option 1,0.2486515531,05MAY1962,01JAN1960:08:47:09,0:00:42,2,23
|
||||||
|
1046,46 bottles of beer on the wall,Option 1,0.4097825794,20JUN1960,01JAN1960:03:33:26,0:00:31,98,71
|
||||||
|
1047,47 bottles of beer on the wall,Option 1,0.138754441,28JAN1960,01JAN1960:00:57:41,0:00:18,80,32
|
||||||
|
1048,48 bottles of beer on the wall,Option 1,0.0249874415,03MAR1960,01JAN1960:11:33:53,0:00:04,96,76
|
||||||
|
1049,49 bottles of beer on the wall,Option 1,0.8395310011,06NOV1961,01JAN1960:09:54:04,0:00:52,28,45
|
||||||
|
1050,50 bottles of beer on the wall,Option 1,0.0942291618,14APR1962,01JAN1960:08:09:30,0:01:36,37,86
|
||||||
|
1051,51 bottles of beer on the wall,Option 1,0.1670458001,13NOV1961,01JAN1960:01:05:55,0:00:25,42,83
|
||||||
|
1052,52 bottles of beer on the wall,Option 1,0.3122402715,04JUN1960,01JAN1960:03:47:47,0:01:01,18,78
|
||||||
|
1053,53 bottles of beer on the wall,Option 1,0.3854694261,14JUN1960,01JAN1960:02:43:08,0:00:06,22,67
|
||||||
|
1054,54 bottles of beer on the wall,Option 1,0.1950434345,14NOV1961,01JAN1960:02:46:34,0:00:55,42,0
|
||||||
|
1055,55 bottles of beer on the wall,Option 1,0.4948673586,29MAR1962,01JAN1960:00:48:06,0:01:04,28,4
|
||||||
|
1056,56 bottles of beer on the wall,Option 1,0.6464513832,06SEP1962,01JAN1960:10:08:36,0:01:02,43,82
|
||||||
|
1057,57 bottles of beer on the wall,Option 1,0.0724864798,20JUN1961,01JAN1960:12:22:51,0:01:27,82,53
|
||||||
|
1058,58 bottles of beer on the wall,Option 1,0.8114467793,20MAR1962,01JAN1960:06:11:33,0:01:29,40,89
|
||||||
|
1059,59 bottles of beer on the wall,Option 1,0.6348024321,28JUN1962,01JAN1960:05:21:21,0:01:37,55,41
|
||||||
|
1060,60 bottles of beer on the wall,Option 1,0.8019492933,08APR1961,01JAN1960:12:37:00,0:01:29,49,88
|
||||||
|
1061,61 bottles of beer on the wall,Option 1,0.4695742002,29JAN1962,01JAN1960:08:54:24,0:00:15,40,91
|
||||||
|
1062,62 bottles of beer on the wall,Option 1,0.902706475,15JUN1961,01JAN1960:09:46:49,0:00:23,74,70
|
||||||
|
1063,63 bottles of beer on the wall,Option 1,0.4557614594,16JUL1961,01JAN1960:02:06:05,0:01:09,7,3
|
||||||
|
1064,64 bottles of beer on the wall,Option 1,0.6632444466,20MAY1961,01JAN1960:02:44:44,0:00:20,42,100
|
||||||
|
1065,65 bottles of beer on the wall,Option 1,0.3901674,31AUG1961,01JAN1960:07:56:49,0:00:32,98,3
|
||||||
|
1066,66 bottles of beer on the wall,Option 1,0.8453234848,30JUN1962,01JAN1960:04:51:54,0:01:02,51,22
|
||||||
|
1067,67 bottles of beer on the wall,Option 1,0.9370150906,26APR1960,01JAN1960:04:05:08,0:01:39,28,86
|
||||||
|
1068,68 bottles of beer on the wall,Option 1,0.8854161277,22MAR1962,01JAN1960:10:38:49,0:01:07,60,85
|
||||||
|
1069,69 bottles of beer on the wall,Option 1,0.1327841906,24MAY1960,01JAN1960:01:18:46,0:01:15,88,85
|
||||||
|
1070,70 bottles of beer on the wall,Option 1,0.5846563226,27JUL1962,01JAN1960:03:52:31,0:00:09,20,8
|
||||||
|
1071,71 bottles of beer on the wall,Option 1,0.0257193684,18FEB1961,01JAN1960:03:25:01,0:00:29,1,62
|
||||||
|
1072,72 bottles of beer on the wall,Option 1,0.9471486034,01JUN1962,01JAN1960:04:05:25,0:01:22,65,20
|
||||||
|
1073,73 bottles of beer on the wall,Option 1,0.3037446282,16MAY1962,01JAN1960:05:10:19,0:00:01,14,34
|
||||||
|
1074,74 bottles of beer on the wall,Option 1,0.2508690675,01NOV1961,01JAN1960:11:26:03,0:00:15,8,74
|
||||||
|
1075,75 bottles of beer on the wall,Option 1,0.814380363,17SEP1960,01JAN1960:09:00:38,0:00:25,95,1
|
||||||
|
1076,76 bottles of beer on the wall,Option 1,0.3761493621,16AUG1961,01JAN1960:01:48:17,0:00:52,5,38
|
||||||
|
1077,77 bottles of beer on the wall,Option 1,0.3621215761,25JUL1961,01JAN1960:11:48:47,0:01:20,86,90
|
||||||
|
1078,78 bottles of beer on the wall,Option 1,0.0268799584,20MAY1961,01JAN1960:12:43:34,0:01:00,70,96
|
||||||
|
1079,79 bottles of beer on the wall,Option 1,0.4112483945,27JUL1962,01JAN1960:01:20:24,0:01:26,66,20
|
||||||
|
1080,80 bottles of beer on the wall,Option 1,0.9501868011,15APR1961,01JAN1960:09:58:20,0:00:51,93,79
|
||||||
|
1081,81 bottles of beer on the wall,Option 1,0.9866548018,13SEP1961,01JAN1960:05:20:04,0:00:14,28,97
|
||||||
|
1082,82 bottles of beer on the wall,Option 1,0.9907830073,22FEB1962,01JAN1960:03:29:03,0:00:17,16,91
|
||||||
|
1083,83 bottles of beer on the wall,Option 1,0.8927816567,11MAR1960,01JAN1960:05:52:48,0:01:26,54,14
|
||||||
|
1084,84 bottles of beer on the wall,Option 1,0.12871663,02FEB1961,01JAN1960:10:34:37,0:00:44,52,90
|
||||||
|
1085,85 bottles of beer on the wall,Option 1,0.5490252802,02JAN1960,01JAN1960:06:11:58,0:00:27,4,98
|
||||||
|
1086,86 bottles of beer on the wall,Option 1,0.5432773864,11FEB1960,01JAN1960:08:40:00,0:01:15,79,19
|
||||||
|
1087,87 bottles of beer on the wall,Option 1,0.8223943137,01OCT1960,01JAN1960:08:11:33,0:01:19,2,86
|
||||||
|
1088,88 bottles of beer on the wall,Option 1,0.8496777699,09FEB1962,01JAN1960:03:10:35,0:00:15,95,6
|
||||||
|
1089,89 bottles of beer on the wall,Option 1,0.9308730536,27MAY1962,01JAN1960:11:57:53,0:01:18,86,90
|
||||||
|
1090,90 bottles of beer on the wall,Option 1,0.3072653344,23FEB1962,01JAN1960:04:52:38,0:00:25,85,17
|
||||||
|
1091,91 bottles of beer on the wall,Option 1,0.7687679575,12FEB1960,01JAN1960:08:47:11,0:01:20,8,7
|
||||||
|
1092,92 bottles of beer on the wall,Option 1,0.1873595105,29SEP1961,01JAN1960:04:29:58,0:00:29,17,78
|
||||||
|
1093,93 bottles of beer on the wall,Option 1,0.0495966631,03OCT1961,01JAN1960:03:18:50,0:00:39,89,56
|
||||||
|
1094,94 bottles of beer on the wall,Option 1,0.2607690526,19SEP1960,01JAN1960:03:22:28,0:00:29,81,16
|
||||||
|
1095,95 bottles of beer on the wall,Option 1,0.549640266,07JUN1962,01JAN1960:06:15:32,0:00:04,57,70
|
||||||
|
1096,96 bottles of beer on the wall,Option 1,0.9993291092,08MAR1961,01JAN1960:13:49:08,0:00:33,37,28
|
||||||
|
1097,97 bottles of beer on the wall,Option 1,0.9517237963,02SEP1960,01JAN1960:05:16:03,0:00:40,77,61
|
||||||
|
1098,98 bottles of beer on the wall,Option 1,0.5952155588,14FEB1962,01JAN1960:05:05:11,0:01:29,63,83
|
||||||
|
1099,99 bottles of beer on the wall,Option 1,0.7526210732,05MAY1961,01JAN1960:06:58:36,0:00:02,95,1
|
||||||
|
10100,100 bottles of beer on the wall,Option 1,0.307558153,17MAY1961,01JAN1960:06:13:01,0:01:37,68,7
|
||||||
|
10101,101 bottles of beer on the wall,Option 1,0.6596710829,15APR1962,01JAN1960:08:34:02,0:00:43,66,43
|
||||||
|
10102,102 bottles of beer on the wall,Option 1,0.0202811998,31AUG1961,01JAN1960:07:22:35,0:01:31,57,35
|
||||||
|
10103,103 bottles of beer on the wall,Option 1,0.6699061034,02MAY1962,01JAN1960:05:13:17,0:00:36,30,23
|
||||||
|
10104,104 bottles of beer on the wall,Option 1,0.330972748,04JUN1961,01JAN1960:06:47:20,0:01:05,69,82
|
||||||
|
10105,105 bottles of beer on the wall,Option 1,0.2274839176,25JAN1961,01JAN1960:05:34:51,0:00:56,63,68
|
||||||
|
10106,106 bottles of beer on the wall,Option 1,0.5612243989,27JUN1962,01JAN1960:04:32:03,0:01:15,19,73
|
||||||
|
10107,107 bottles of beer on the wall,Option 1,0.7398902111,03SEP1962,01JAN1960:08:34:07,0:00:17,90,6
|
||||||
|
10108,108 bottles of beer on the wall,Option 1,0.6124899791,08AUG1960,01JAN1960:04:59:34,0:00:25,56,12
|
||||||
|
10109,109 bottles of beer on the wall,Option 1,0.882404773,26JAN1961,01JAN1960:01:29:15,0:01:26,36,4
|
||||||
|
10110,110 bottles of beer on the wall,Option 1,0.4427004733,27FEB1961,01JAN1960:06:16:49,0:01:40,97,84
|
||||||
|
10111,111 bottles of beer on the wall,Option 1,0.3609524622,10JAN1962,01JAN1960:09:48:37,0:01:11,87,62
|
||||||
|
10112,112 bottles of beer on the wall,Option 1,0.9408929562,03AUG1960,01JAN1960:06:54:26,0:00:08,19,33
|
||||||
|
10113,113 bottles of beer on the wall,Option 1,0.3149107319,10AUG1962,01JAN1960:13:01:00,0:00:04,75,60
|
||||||
|
10114,114 bottles of beer on the wall,Option 1,0.0525069181,17APR1962,01JAN1960:13:00:52,0:00:35,9,23
|
||||||
|
10115,115 bottles of beer on the wall,Option 1,0.145448105,14FEB1962,01JAN1960:04:06:08,0:00:26,45,91
|
||||||
|
10116,116 bottles of beer on the wall,Option 1,0.2444279959,10OCT1961,01JAN1960:08:03:12,0:01:37,12,41
|
||||||
|
10117,117 bottles of beer on the wall,Option 1,0.4619846043,30JUL1960,01JAN1960:09:40:16,0:00:50,2,88
|
||||||
|
10118,118 bottles of beer on the wall,Option 1,0.0316203502,13JUL1961,01JAN1960:08:31:39,0:01:05,60,94
|
||||||
|
10119,119 bottles of beer on the wall,Option 1,0.4738720574,13AUG1960,01JAN1960:01:31:05,0:01:17,43,79
|
||||||
|
10120,120 bottles of beer on the wall,Option 1,0.8058761856,11JUN1960,01JAN1960:12:56:35,0:00:08,92,36
|
||||||
|
10121,121 bottles of beer on the wall,Option 1,0.2955600979,08JUL1962,01JAN1960:06:09:22,0:00:03,94,80
|
||||||
|
10122,122 bottles of beer on the wall,Option 1,0.0064115427,18SEP1962,01JAN1960:00:06:24,0:00:13,72,75
|
||||||
|
10123,123 bottles of beer on the wall,Option 1,0.5678159327,21APR1960,01JAN1960:10:54:21,0:00:16,75,67
|
||||||
|
10124,124 bottles of beer on the wall,Option 1,0.1431510994,10JAN1962,01JAN1960:01:57:00,0:00:12,48,31
|
||||||
|
10125,125 bottles of beer on the wall,Option 1,0.3805634409,26JAN1962,01JAN1960:03:03:19,0:01:29,83,52
|
||||||
|
10126,126 bottles of beer on the wall,Option 1,0.3833517993,26APR1960,01JAN1960:11:27:41,0:00:44,99,36
|
||||||
|
10127,127 bottles of beer on the wall,Option 1,0.5669089111,04MAR1961,01JAN1960:05:36:22,0:01:18,43,27
|
||||||
|
10128,128 bottles of beer on the wall,Option 1,0.1514211843,01NOV1960,01JAN1960:07:45:50,0:01:02,22,12
|
||||||
|
10129,129 bottles of beer on the wall,Option 1,0.0446588583,05JAN1961,01JAN1960:02:13:55,0:00:42,27,46
|
||||||
|
10130,130 bottles of beer on the wall,Option 1,0.7892141611,22APR1962,01JAN1960:04:17:54,0:01:05,75,84
|
||||||
|
10131,131 bottles of beer on the wall,Option 1,0.5012088001,24DEC1960,01JAN1960:13:03:23,0:01:22,87,82
|
||||||
|
10132,132 bottles of beer on the wall,Option 1,0.2327582944,07APR1961,01JAN1960:01:33:15,0:01:14,18,46
|
||||||
|
10133,133 bottles of beer on the wall,Option 1,0.2234651173,20MAR1961,01JAN1960:13:52:02,0:01:06,42,58
|
||||||
|
10134,134 bottles of beer on the wall,Option 1,0.4954405918,10FEB1961,01JAN1960:13:51:14,0:01:36,35,11
|
||||||
|
10135,135 bottles of beer on the wall,Option 1,0.7874922891,15AUG1960,01JAN1960:00:21:57,0:00:52,45,36
|
||||||
|
10136,136 bottles of beer on the wall,Option 1,0.3992494891,06SEP1961,01JAN1960:09:51:46,0:01:25,26,9
|
||||||
|
10137,137 bottles of beer on the wall,Option 1,0.3964866136,25MAY1960,01JAN1960:03:19:48,0:00:28,44,3
|
||||||
|
10138,138 bottles of beer on the wall,Option 1,0.9466173323,06APR1962,01JAN1960:13:19:18,0:01:27,78,51
|
||||||
|
10139,139 bottles of beer on the wall,Option 1,0.6525219277,09APR1960,01JAN1960:05:43:49,0:00:21,63,6
|
||||||
|
10140,140 bottles of beer on the wall,Option 1,0.4684071925,29MAY1961,01JAN1960:02:53:36,0:00:46,68,4
|
||||||
|
10141,141 bottles of beer on the wall,Option 1,0.8581724013,16MAY1960,01JAN1960:01:45:44,0:01:32,31,85
|
||||||
|
10142,142 bottles of beer on the wall,Option 1,0.825792401,23APR1961,01JAN1960:12:03:13,0:00:49,36,45
|
||||||
|
10143,143 bottles of beer on the wall,Option 1,0.3172852538,20FEB1962,01JAN1960:12:38:31,0:01:34,51,78
|
||||||
|
10144,144 bottles of beer on the wall,Option 1,0.670397946,27JAN1962,01JAN1960:04:59:37,0:00:39,38,99
|
||||||
|
10145,145 bottles of beer on the wall,Option 1,0.3304372441,04JUN1960,01JAN1960:00:39:12,0:00:29,88,76
|
||||||
|
10146,146 bottles of beer on the wall,Option 1,0.845151971,31JUL1962,01JAN1960:05:03:34,0:00:13,2,80
|
||||||
|
10147,147 bottles of beer on the wall,Option 1,0.7957223709,02FEB1961,01JAN1960:00:03:07,0:01:11,29,99
|
||||||
|
10148,148 bottles of beer on the wall,Option 1,0.323337108,29FEB1960,01JAN1960:01:58:05,0:01:17,23,65
|
||||||
|
10149,149 bottles of beer on the wall,Option 1,0.1813316611,29JUN1960,01JAN1960:02:18:08,0:00:40,45,52
|
||||||
|
10150,150 bottles of beer on the wall,Option 1,0.7860426655,05MAR1962,01JAN1960:01:57:15,0:00:26,31,91
|
||||||
|
10151,151 bottles of beer on the wall,Option 1,0.3305453571,09APR1960,01JAN1960:07:08:32,0:01:30,72,15
|
||||||
|
10152,152 bottles of beer on the wall,Option 1,0.9367212513,18AUG1962,01JAN1960:10:36:03,0:01:26,85,81
|
||||||
|
10153,153 bottles of beer on the wall,Option 1,0.3385623458,19MAR1962,01JAN1960:04:21:46,0:01:29,11,54
|
||||||
|
10154,154 bottles of beer on the wall,Option 1,0.9756794413,17JUN1961,01JAN1960:08:35:40,0:00:34,3,72
|
||||||
|
10155,155 bottles of beer on the wall,Option 1,0.6385958868,21OCT1961,01JAN1960:08:51:00,0:00:50,1,6
|
||||||
|
10156,156 bottles of beer on the wall,Option 1,0.3569769959,14AUG1960,01JAN1960:10:57:16,0:00:05,5,94
|
||||||
|
10157,157 bottles of beer on the wall,Option 1,0.8559997239,23MAR1962,01JAN1960:12:03:38,0:00:08,96,68
|
||||||
|
10158,158 bottles of beer on the wall,Option 1,0.2293701918,13AUG1960,01JAN1960:06:36:47,0:00:07,87,87
|
||||||
|
10159,159 bottles of beer on the wall,Option 1,0.0007910165,20SEP1962,01JAN1960:11:49:02,0:00:55,18,69
|
||||||
|
10160,160 bottles of beer on the wall,Option 1,0.5876370373,08JAN1960,01JAN1960:00:59:15,0:01:26,27,36
|
||||||
|
10161,161 bottles of beer on the wall,Option 1,0.2354667514,11OCT1961,01JAN1960:01:27:14,0:01:04,90,28
|
||||||
|
10162,162 bottles of beer on the wall,Option 1,0.0144103263,11AUG1961,01JAN1960:02:37:41,0:01:39,92,8
|
||||||
|
10163,163 bottles of beer on the wall,Option 1,0.7087855668,03JUL1962,01JAN1960:02:07:23,0:01:35,51,33
|
||||||
|
10164,164 bottles of beer on the wall,Option 1,0.7251478106,20MAY1960,01JAN1960:12:15:23,0:01:28,58,7
|
||||||
|
10165,165 bottles of beer on the wall,Option 1,0.9629398403,06APR1962,01JAN1960:01:05:24,0:01:39,84,6
|
||||||
|
10166,166 bottles of beer on the wall,Option 1,0.5155049164,14OCT1960,01JAN1960:04:02:06,0:00:30,63,96
|
||||||
|
10167,167 bottles of beer on the wall,Option 1,0.1016342775,11MAY1960,01JAN1960:05:55:03,0:00:01,31,44
|
||||||
|
10168,168 bottles of beer on the wall,Option 1,0.3690353596,12NOV1961,01JAN1960:12:49:02,0:00:03,2,79
|
||||||
|
10169,169 bottles of beer on the wall,Option 1,0.5573803501,02SEP1962,01JAN1960:12:59:56,0:00:31,7,95
|
||||||
|
10170,170 bottles of beer on the wall,Option 1,0.2008119497,10JUN1961,01JAN1960:05:59:06,0:01:29,88,4
|
||||||
|
10171,171 bottles of beer on the wall,Option 1,0.6939068505,25MAY1962,01JAN1960:07:20:06,0:01:08,87,8
|
||||||
|
10172,172 bottles of beer on the wall,Option 1,0.7013406594,14JUL1960,01JAN1960:04:04:24,0:00:11,44,96
|
||||||
|
10173,173 bottles of beer on the wall,Option 1,0.83506724,30APR1961,01JAN1960:12:44:40,0:00:10,74,70
|
||||||
|
10174,174 bottles of beer on the wall,Option 1,0.9339991943,26JAN1962,01JAN1960:04:59:32,0:01:09,13,66
|
||||||
|
10175,175 bottles of beer on the wall,Option 1,0.8333402787,18FEB1961,01JAN1960:07:25:44,0:00:28,47,2
|
||||||
|
10176,176 bottles of beer on the wall,Option 1,0.5998844433,03MAR1962,01JAN1960:03:45:33,0:00:52,2,61
|
||||||
|
10177,177 bottles of beer on the wall,Option 1,0.6161394634,18DEC1960,01JAN1960:05:35:25,0:00:50,70,22
|
||||||
|
10178,178 bottles of beer on the wall,Option 1,0.0821002392,21APR1960,01JAN1960:10:08:56,0:01:40,28,9
|
||||||
|
10179,179 bottles of beer on the wall,Option 1,0.6845213462,23MAY1960,01JAN1960:13:15:46,0:00:03,89,13
|
||||||
|
10180,180 bottles of beer on the wall,Option 1,0.3839034477,14MAY1960,01JAN1960:03:22:17,0:01:11,15,38
|
||||||
|
10181,181 bottles of beer on the wall,Option 1,0.7949567609,21AUG1962,01JAN1960:02:41:01,0:00:57,90,93
|
||||||
|
10182,182 bottles of beer on the wall,Option 1,0.5079025419,23SEP1962,01JAN1960:02:22:31,0:01:07,83,32
|
||||||
|
10183,183 bottles of beer on the wall,Option 1,0.3215162574,26DEC1961,01JAN1960:09:03:00,0:01:38,46,94
|
||||||
|
10184,184 bottles of beer on the wall,Option 1,0.3322958058,12MAY1961,01JAN1960:02:48:05,0:00:46,80,54
|
||||||
|
10185,185 bottles of beer on the wall,Option 1,0.6510801453,07SEP1960,01JAN1960:11:49:02,0:00:59,51,47
|
||||||
|
10186,186 bottles of beer on the wall,Option 1,0.060995535,15AUG1960,01JAN1960:02:21:08,0:01:40,5,61
|
||||||
|
10187,187 bottles of beer on the wall,Option 1,0.8541180551,14SEP1960,01JAN1960:13:29:33,0:01:23,17,14
|
||||||
|
10188,188 bottles of beer on the wall,Option 1,0.9427926219,23JUL1960,01JAN1960:05:19:05,0:01:13,22,97
|
||||||
|
10189,189 bottles of beer on the wall,Option 1,0.2325015186,01FEB1960,01JAN1960:11:50:07,0:01:22,6,53
|
||||||
|
10190,190 bottles of beer on the wall,Option 1,0.3687101493,21FEB1962,01JAN1960:06:44:23,0:00:13,16,30
|
||||||
|
10191,191 bottles of beer on the wall,Option 1,0.7647511232,09JAN1960,01JAN1960:13:06:29,0:01:35,6,97
|
||||||
|
10192,192 bottles of beer on the wall,Option 1,0.4105463565,17AUG1961,01JAN1960:11:04:32,0:01:14,38,33
|
||||||
|
10193,193 bottles of beer on the wall,Option 1,0.8785403831,12JUL1962,01JAN1960:04:11:05,0:00:29,19,82
|
||||||
|
10194,194 bottles of beer on the wall,Option 1,0.9304303433,11JUL1961,01JAN1960:12:36:57,0:01:02,20,35
|
||||||
|
10195,195 bottles of beer on the wall,Option 1,0.7302505256,01MAR1961,01JAN1960:01:38:35,0:00:42,16,35
|
||||||
|
10196,196 bottles of beer on the wall,Option 1,0.2536906177,04SEP1962,01JAN1960:05:18:23,0:01:18,91,50
|
||||||
|
10197,197 bottles of beer on the wall,Option 1,0.1181504503,08AUG1961,01JAN1960:09:27:54,0:01:26,20,13
|
||||||
|
10198,198 bottles of beer on the wall,Option 1,0.9275614228,17JUL1961,01JAN1960:01:52:18,0:00:06,52,73
|
||||||
|
10199,199 bottles of beer on the wall,Option 1,0.7495222128,04APR1961,01JAN1960:09:28:04,0:00:42,30,41
|
||||||
|
10200,200 bottles of beer on the wall,Option 1,0.925741082,02FEB1962,01JAN1960:12:23:10,0:00:07,79,17
|
||||||
|
10201,201 bottles of beer on the wall,Option 1,0.2591843359,04DEC1960,01JAN1960:12:46:41,0:00:00,53,58
|
||||||
|
10202,202 bottles of beer on the wall,Option 1,0.4289995704,17NOV1961,01JAN1960:02:20:52,0:00:35,41,25
|
||||||
|
10203,203 bottles of beer on the wall,Option 1,0.4625803807,24JAN1960,01JAN1960:08:20:44,0:01:11,84,66
|
||||||
|
10204,204 bottles of beer on the wall,Option 1,0.858440102,31AUG1962,01JAN1960:08:51:40,0:00:12,18,51
|
||||||
|
10205,205 bottles of beer on the wall,Option 1,0.8964499016,01SEP1962,01JAN1960:05:33:47,0:00:23,34,77
|
||||||
|
10206,206 bottles of beer on the wall,Option 1,0.5742789063,24OCT1961,01JAN1960:02:31:04,0:01:08,27,66
|
||||||
|
10207,207 bottles of beer on the wall,Option 1,0.4864150954,29SEP1960,01JAN1960:09:27:46,0:01:28,31,26
|
||||||
|
10208,208 bottles of beer on the wall,Option 1,0.4511992249,04DEC1960,01JAN1960:09:39:26,0:00:42,49,98
|
||||||
|
10209,209 bottles of beer on the wall,Option 1,0.4218624157,13SEP1961,01JAN1960:01:40:55,0:01:39,35,50
|
||||||
|
10210,210 bottles of beer on the wall,Option 1,0.1572868331,15FEB1960,01JAN1960:07:01:15,0:00:51,43,1
|
||||||
|
10211,211 bottles of beer on the wall,Option 1,0.713915177,23MAR1960,01JAN1960:11:08:53,0:00:15,18,61
|
||||||
|
10212,212 bottles of beer on the wall,Option 1,0.5677882165,19MAY1960,01JAN1960:01:27:23,0:01:02,34,89
|
||||||
|
10213,213 bottles of beer on the wall,Option 1,0.7552938581,12SEP1961,01JAN1960:11:47:33,0:00:38,44,46
|
||||||
|
10214,214 bottles of beer on the wall,Option 1,0.6071256071,28DEC1961,01JAN1960:05:28:18,0:01:23,84,66
|
||||||
|
10215,215 bottles of beer on the wall,Option 1,0.7717189266,12MAR1960,01JAN1960:01:21:26,0:01:00,28,22
|
||||||
|
10216,216 bottles of beer on the wall,Option 1,0.8985594329,24MAR1961,01JAN1960:10:48:58,0:01:31,93,2
|
||||||
|
10217,217 bottles of beer on the wall,Option 1,0.3156879904,13AUG1960,01JAN1960:07:10:46,0:01:18,100,54
|
||||||
|
10218,218 bottles of beer on the wall,Option 1,0.3408455315,08JUN1961,01JAN1960:02:26:49,0:00:05,65,82
|
||||||
|
10219,219 bottles of beer on the wall,Option 1,0.6263580553,08JUN1962,01JAN1960:05:59:46,0:01:03,76,88
|
||||||
|
10220,220 bottles of beer on the wall,Option 1,0.2878925355,19DEC1961,01JAN1960:08:23:41,0:00:00,92,1
|
||||||
|
10221,221 bottles of beer on the wall,Option 1,0.0901017348,19JUL1962,01JAN1960:09:50:47,0:00:43,21,84
|
||||||
|
10222,222 bottles of beer on the wall,Option 1,0.8967759362,14SEP1960,01JAN1960:12:25:58,0:01:22,34,50
|
||||||
|
10223,223 bottles of beer on the wall,Option 1,0.9878171943,03DEC1961,01JAN1960:03:43:09,0:00:17,11,84
|
||||||
|
10224,224 bottles of beer on the wall,Option 1,0.5275036886,13DEC1961,01JAN1960:03:12:56,0:01:36,85,49
|
||||||
|
10225,225 bottles of beer on the wall,Option 1,0.442012436,12JUN1960,01JAN1960:11:40:23,0:01:40,76,87
|
||||||
|
10226,226 bottles of beer on the wall,Option 1,0.582103689,10FEB1961,01JAN1960:01:50:49,0:00:59,53,29
|
||||||
|
10227,227 bottles of beer on the wall,Option 1,0.5757669842,01NOV1960,01JAN1960:13:47:33,0:00:43,55,6
|
||||||
|
10228,228 bottles of beer on the wall,Option 1,0.4786617507,07JAN1960,01JAN1960:13:36:24,0:01:22,91,53
|
||||||
|
10229,229 bottles of beer on the wall,Option 1,0.1386274957,06APR1962,01JAN1960:03:48:29,0:01:27,36,48
|
||||||
|
10230,230 bottles of beer on the wall,Option 1,0.4188394893,31MAY1962,01JAN1960:10:30:51,0:00:54,5,87
|
||||||
|
10231,231 bottles of beer on the wall,Option 1,0.9250617777,18OCT1960,01JAN1960:04:29:52,0:00:38,34,94
|
||||||
|
10232,232 bottles of beer on the wall,Option 1,0.3077528124,05FEB1960,01JAN1960:09:37:42,0:01:13,58,75
|
||||||
|
10233,233 bottles of beer on the wall,Option 1,0.7316332277,29NOV1960,01JAN1960:08:56:57,0:01:13,34,53
|
||||||
|
10234,234 bottles of beer on the wall,Option 1,0.5666298352,21NOV1960,01JAN1960:07:51:09,0:01:08,97,71
|
||||||
|
10235,235 bottles of beer on the wall,Option 1,0.5736639409,03JUL1962,01JAN1960:11:57:25,0:00:51,15,49
|
||||||
|
10236,236 bottles of beer on the wall,Option 1,0.6785667616,11FEB1962,01JAN1960:09:47:20,0:00:50,65,21
|
||||||
|
10237,237 bottles of beer on the wall,Option 1,0.3721726869,05JUL1962,01JAN1960:11:58:22,0:01:32,82,21
|
||||||
|
10238,238 bottles of beer on the wall,Option 1,0.0332283876,17AUG1961,01JAN1960:13:11:34,0:00:54,83,30
|
||||||
|
10239,239 bottles of beer on the wall,Option 1,0.9734656848,02JAN1961,01JAN1960:00:36:43,0:00:19,31,54
|
||||||
|
10240,240 bottles of beer on the wall,Option 1,0.3022106021,16FEB1961,01JAN1960:13:50:38,0:00:40,22,66
|
||||||
|
10241,241 bottles of beer on the wall,Option 1,0.7546903294,06JUL1961,01JAN1960:12:36:17,0:01:29,16,85
|
||||||
|
10242,242 bottles of beer on the wall,Option 1,0.2509871834,07MAR1962,01JAN1960:10:38:28,0:00:39,7,8
|
||||||
|
10243,243 bottles of beer on the wall,Option 1,0.9526996668,15JAN1960,01JAN1960:04:24:42,0:01:01,69,80
|
||||||
|
10244,244 bottles of beer on the wall,Option 1,0.1816610122,06FEB1962,01JAN1960:08:46:51,0:00:54,89,91
|
||||||
|
10245,245 bottles of beer on the wall,Option 1,0.3928658876,21JUL1962,01JAN1960:12:59:42,0:00:38,24,27
|
||||||
|
10246,246 bottles of beer on the wall,Option 1,0.3774878524,18FEB1961,01JAN1960:07:40:49,0:01:31,88,93
|
||||||
|
10247,247 bottles of beer on the wall,Option 1,0.6063659362,01NOV1960,01JAN1960:01:19:07,0:00:05,82,73
|
||||||
|
10248,248 bottles of beer on the wall,Option 1,0.119603098,14JUN1960,01JAN1960:04:29:22,0:00:58,87,47
|
||||||
|
10249,249 bottles of beer on the wall,Option 1,0.4833748445,03JUL1960,01JAN1960:01:53:54,0:00:37,34,33
|
||||||
|
10250,250 bottles of beer on the wall,Option 1,0.2244539946,10AUG1961,01JAN1960:06:19:01,0:01:15,87,97
|
||||||
|
10251,251 bottles of beer on the wall,Option 1,0.9368193191,11JUN1962,01JAN1960:06:37:14,0:00:46,94,39
|
||||||
|
10252,252 bottles of beer on the wall,Option 1,0.1791427751,10NOV1961,01JAN1960:00:49:22,0:00:47,96,21
|
||||||
|
10253,253 bottles of beer on the wall,Option 1,0.5836302874,06JUN1961,01JAN1960:08:39:34,0:01:01,78,49
|
||||||
|
10254,254 bottles of beer on the wall,Option 1,0.1289398275,28DEC1960,01JAN1960:12:25:05,0:00:43,67,99
|
||||||
|
10255,255 bottles of beer on the wall,Option 1,0.7833669785,05SEP1962,01JAN1960:02:47:35,0:00:20,25,2
|
||||||
|
10256,256 bottles of beer on the wall,Option 1,0.4945342483,29JAN1960,01JAN1960:00:54:13,0:01:13,72,56
|
||||||
|
10257,257 bottles of beer on the wall,Option 1,0.0635836129,05JAN1961,01JAN1960:08:10:04,0:00:52,11,10
|
||||||
|
10258,258 bottles of beer on the wall,Option 1,0.8188241654,09FEB1962,01JAN1960:06:33:00,0:01:21,41,96
|
||||||
|
10259,259 bottles of beer on the wall,Option 1,0.3398916076,11FEB1960,01JAN1960:07:12:29,0:00:56,18,76
|
||||||
|
10260,260 bottles of beer on the wall,Option 1,0.0814064155,21MAY1961,01JAN1960:11:03:51,0:01:18,78,29
|
||||||
|
10261,261 bottles of beer on the wall,Option 1,0.6653245542,20JAN1962,01JAN1960:08:03:31,0:00:18,39,95
|
||||||
|
10262,262 bottles of beer on the wall,Option 1,0.4036777021,04AUG1962,01JAN1960:12:32:27,0:00:08,57,63
|
||||||
|
10263,263 bottles of beer on the wall,Option 1,0.8931138603,07JAN1962,01JAN1960:09:04:24,0:00:32,6,27
|
||||||
|
10264,264 bottles of beer on the wall,Option 1,0.528584433,06APR1962,01JAN1960:09:43:19,0:01:00,24,41
|
||||||
|
10265,265 bottles of beer on the wall,Option 1,0.8267822945,29JUL1960,01JAN1960:00:48:11,0:00:01,81,78
|
||||||
|
10266,266 bottles of beer on the wall,Option 1,0.7218411401,17FEB1960,01JAN1960:07:30:38,0:00:08,35,81
|
||||||
|
10267,267 bottles of beer on the wall,Option 1,0.1475262773,11NOV1960,01JAN1960:13:44:20,0:00:57,36,68
|
||||||
|
10268,268 bottles of beer on the wall,Option 1,0.9412727286,30DEC1960,01JAN1960:02:46:30,0:01:19,5,92
|
||||||
|
10269,269 bottles of beer on the wall,Option 1,0.3038877548,27NOV1960,01JAN1960:10:50:10,0:01:21,43,95
|
||||||
|
10270,270 bottles of beer on the wall,Option 1,0.2756435532,15APR1962,01JAN1960:09:05:28,0:01:34,11,14
|
||||||
|
10271,271 bottles of beer on the wall,Option 1,0.7056001121,31AUG1960,01JAN1960:08:48:52,0:00:02,9,51
|
||||||
|
10272,272 bottles of beer on the wall,Option 1,0.5273708508,21SEP1962,01JAN1960:12:58:13,0:00:28,97,69
|
||||||
|
10273,273 bottles of beer on the wall,Option 1,0.6002807215,03MAY1960,01JAN1960:10:14:48,0:00:40,52,32
|
||||||
|
10274,274 bottles of beer on the wall,Option 1,0.6100557971,20JUN1960,01JAN1960:08:11:55,0:00:27,90,14
|
||||||
|
10275,275 bottles of beer on the wall,Option 1,0.4197408638,07JUN1961,01JAN1960:12:07:18,0:00:26,64,100
|
||||||
|
10276,276 bottles of beer on the wall,Option 1,0.4903712498,19JAN1960,01JAN1960:01:06:26,0:00:03,35,24
|
||||||
|
10277,277 bottles of beer on the wall,Option 1,0.6658435406,04NOV1960,01JAN1960:00:04:17,0:00:37,7,84
|
||||||
|
10278,278 bottles of beer on the wall,Option 1,0.5491365942,14JAN1961,01JAN1960:04:12:49,0:00:27,99,47
|
||||||
|
10279,279 bottles of beer on the wall,Option 1,0.4473488622,13MAY1961,01JAN1960:12:06:34,0:01:16,19,20
|
||||||
|
10280,280 bottles of beer on the wall,Option 1,0.4511988663,06JUL1962,01JAN1960:10:05:51,0:00:56,76,34
|
||||||
|
10281,281 bottles of beer on the wall,Option 1,0.0783031066,11JUN1961,01JAN1960:09:58:43,0:01:05,9,63
|
||||||
|
10282,282 bottles of beer on the wall,Option 1,0.776985302,20JUL1962,01JAN1960:10:44:29,0:01:00,59,10
|
||||||
|
10283,283 bottles of beer on the wall,Option 1,0.468099362,31AUG1962,01JAN1960:05:26:33,0:00:20,35,52
|
||||||
|
10284,284 bottles of beer on the wall,Option 1,0.4040679696,20FEB1962,01JAN1960:06:27:25,0:00:04,76,30
|
||||||
|
10285,285 bottles of beer on the wall,Option 1,0.4549995947,20FEB1962,01JAN1960:10:36:57,0:00:34,2,43
|
||||||
|
10286,286 bottles of beer on the wall,Option 1,0.7455339361,16SEP1961,01JAN1960:08:39:35,0:01:00,42,44
|
||||||
|
10287,287 bottles of beer on the wall,Option 1,0.0209561712,04JAN1960,01JAN1960:05:52:58,0:00:24,32,7
|
||||||
|
10288,288 bottles of beer on the wall,Option 1,0.4955981842,04JAN1962,01JAN1960:02:56:03,0:00:30,85,31
|
||||||
|
10289,289 bottles of beer on the wall,Option 1,0.4131368219,10FEB1960,01JAN1960:11:57:31,0:00:16,37,88
|
||||||
|
10290,290 bottles of beer on the wall,Option 1,0.3282186721,17OCT1960,01JAN1960:10:54:04,0:00:56,72,28
|
||||||
|
10291,291 bottles of beer on the wall,Option 1,0.2116929005,18JAN1962,01JAN1960:06:56:27,0:00:11,87,82
|
||||||
|
10292,292 bottles of beer on the wall,Option 1,0.8483731937,12FEB1962,01JAN1960:05:05:41,0:01:36,12,83
|
||||||
|
10293,293 bottles of beer on the wall,Option 1,0.1560111345,13NOV1960,01JAN1960:10:04:22,0:00:03,94,4
|
||||||
|
10294,294 bottles of beer on the wall,Option 1,0.7046207808,12APR1962,01JAN1960:13:50:47,0:00:32,31,97
|
||||||
|
10295,295 bottles of beer on the wall,Option 1,0.2716620403,04AUG1961,01JAN1960:01:52:29,0:00:57,99,44
|
||||||
|
10296,296 bottles of beer on the wall,Option 1,0.5543203496,12SEP1960,01JAN1960:13:43:54,0:00:44,49,1
|
||||||
|
10297,297 bottles of beer on the wall,Option 1,0.983109036,31JUL1962,01JAN1960:01:07:33,0:00:36,4,10
|
||||||
|
10298,298 bottles of beer on the wall,Option 1,0.8123072115,14SEP1962,01JAN1960:06:16:12,0:01:25,88,96
|
||||||
|
10299,299 bottles of beer on the wall,Option 1,0.4276896559,05OCT1960,01JAN1960:02:55:07,0:00:58,83,76
|
||||||
|
10300,300 bottles of beer on the wall,Option 1,0.8921809042,19JAN1962,01JAN1960:02:05:38,0:00:12,80,13
|
||||||
|
10301,301 bottles of beer on the wall,Option 1,0.6041374279,10DEC1961,01JAN1960:01:06:29,0:01:27,62,9
|
||||||
|
10302,302 bottles of beer on the wall,Option 1,0.0460550185,31MAY1962,01JAN1960:03:03:56,0:00:05,33,88
|
||||||
|
10303,303 bottles of beer on the wall,Option 1,0.1868385622,12APR1962,01JAN1960:12:42:44,0:01:05,65,18
|
||||||
|
10304,304 bottles of beer on the wall,Option 1,0.3386632657,28SEP1961,01JAN1960:11:24:06,0:00:42,2,93
|
||||||
|
10305,305 bottles of beer on the wall,Option 1,0.6400271019,01JUN1960,01JAN1960:13:33:07,0:01:30,60,72
|
||||||
|
10306,306 bottles of beer on the wall,Option 1,0.9534907304,18NOV1961,01JAN1960:02:02:51,0:00:54,7,57
|
||||||
|
10307,307 bottles of beer on the wall,Option 1,0.6663103745,06SEP1961,01JAN1960:05:36:49,0:00:43,88,2
|
||||||
|
10308,308 bottles of beer on the wall,Option 1,0.5392553073,13FEB1962,01JAN1960:11:28:18,0:01:08,16,8
|
||||||
|
10309,309 bottles of beer on the wall,Option 1,0.0747909025,17OCT1961,01JAN1960:08:36:12,0:00:41,49,42
|
||||||
|
10310,310 bottles of beer on the wall,Option 1,0.3249381847,30SEP1960,01JAN1960:08:12:54,0:00:09,96,89
|
||||||
|
10311,311 bottles of beer on the wall,Option 1,0.9231011951,19MAY1962,01JAN1960:05:10:33,0:00:50,30,9
|
||||||
|
10312,312 bottles of beer on the wall,Option 1,0.4658221637,21MAY1961,01JAN1960:12:55:25,0:01:39,16,20
|
||||||
|
10313,313 bottles of beer on the wall,Option 1,0.7215524673,21FEB1960,01JAN1960:02:00:07,0:01:40,95,94
|
||||||
|
10314,314 bottles of beer on the wall,Option 1,0.7328679942,28OCT1961,01JAN1960:09:07:00,0:00:25,42,71
|
||||||
|
10315,315 bottles of beer on the wall,Option 1,0.1276036776,12JUN1960,01JAN1960:01:54:08,0:00:56,57,42
|
||||||
|
10316,316 bottles of beer on the wall,Option 1,0.1270824723,15SEP1960,01JAN1960:03:19:25,0:00:21,85,9
|
||||||
|
10317,317 bottles of beer on the wall,Option 1,0.3750520117,13JUN1961,01JAN1960:04:33:09,0:01:15,24,20
|
||||||
|
10318,318 bottles of beer on the wall,Option 1,0.5777822102,10DEC1960,01JAN1960:13:32:14,0:00:09,98,28
|
||||||
|
10319,319 bottles of beer on the wall,Option 1,0.140476402,27AUG1962,01JAN1960:08:52:46,0:01:08,64,83
|
||||||
|
10320,320 bottles of beer on the wall,Option 1,0.2589205551,31MAY1961,01JAN1960:08:33:06,0:00:53,28,98
|
||||||
|
10321,321 bottles of beer on the wall,Option 1,0.7350722825,16SEP1962,01JAN1960:05:47:44,0:01:17,79,95
|
||||||
|
10322,322 bottles of beer on the wall,Option 1,0.1476364542,15JAN1960,01JAN1960:12:21:20,0:00:20,86,62
|
||||||
|
10323,323 bottles of beer on the wall,Option 1,0.8700561099,15MAY1962,01JAN1960:00:47:05,0:00:20,90,15
|
||||||
|
10324,324 bottles of beer on the wall,Option 1,0.6408788802,12SEP1962,01JAN1960:11:50:31,0:00:53,41,72
|
||||||
|
10325,325 bottles of beer on the wall,Option 1,0.6961101623,27NOV1960,01JAN1960:00:10:49,0:01:17,28,72
|
||||||
|
10326,326 bottles of beer on the wall,Option 1,0.1467710059,24FEB1961,01JAN1960:01:13:38,0:00:33,14,5
|
||||||
|
10327,327 bottles of beer on the wall,Option 1,0.0215573572,09JUN1961,01JAN1960:11:47:17,0:00:21,57,10
|
||||||
|
10328,328 bottles of beer on the wall,Option 1,0.4173900054,25JUL1962,01JAN1960:12:28:20,0:00:23,73,90
|
||||||
|
10329,329 bottles of beer on the wall,Option 1,0.6395625713,02NOV1961,01JAN1960:08:49:34,0:00:37,77,79
|
||||||
|
10330,330 bottles of beer on the wall,Option 1,0.0091438908,18MAY1962,01JAN1960:05:10:05,0:00:41,15,31
|
||||||
|
10331,331 bottles of beer on the wall,Option 1,0.1024675197,11DEC1960,01JAN1960:13:12:57,0:00:23,50,13
|
||||||
|
10332,332 bottles of beer on the wall,Option 1,0.057470562,11MAY1961,01JAN1960:03:43:04,0:00:17,48,14
|
||||||
|
10333,333 bottles of beer on the wall,Option 1,0.8478633872,21JUL1961,01JAN1960:03:45:42,0:01:31,22,40
|
||||||
|
10334,334 bottles of beer on the wall,Option 1,0.3442252541,24JUN1960,01JAN1960:01:19:31,0:00:48,82,25
|
||||||
|
10335,335 bottles of beer on the wall,Option 1,0.7338460184,06JUN1962,01JAN1960:03:32:34,0:01:04,6,31
|
||||||
|
10336,336 bottles of beer on the wall,Option 1,0.6217917342,09MAR1961,01JAN1960:06:37:39,0:00:50,70,84
|
||||||
|
10337,337 bottles of beer on the wall,Option 1,0.6684890807,10OCT1961,01JAN1960:05:34:24,0:01:20,66,18
|
||||||
|
10338,338 bottles of beer on the wall,Option 1,0.3695247562,05SEP1962,01JAN1960:00:25:21,0:01:18,48,37
|
||||||
|
10339,339 bottles of beer on the wall,Option 1,0.9429265987,06DEC1960,01JAN1960:07:11:17,0:00:38,59,1
|
||||||
|
10340,340 bottles of beer on the wall,Option 1,0.9266307265,17JUL1960,01JAN1960:06:33:59,0:00:21,12,13
|
||||||
|
10341,341 bottles of beer on the wall,Option 1,0.7280535543,23FEB1961,01JAN1960:05:01:10,0:00:34,73,25
|
||||||
|
10342,342 bottles of beer on the wall,Option 1,0.488654495,15AUG1962,01JAN1960:01:24:33,0:00:56,59,25
|
||||||
|
10343,343 bottles of beer on the wall,Option 1,0.9526806548,28DEC1960,01JAN1960:07:26:17,0:00:58,97,61
|
||||||
|
10344,344 bottles of beer on the wall,Option 1,0.526025336,14JAN1960,01JAN1960:10:02:08,0:00:55,11,77
|
||||||
|
10345,345 bottles of beer on the wall,Option 1,0.807215352,03JUL1961,01JAN1960:12:49:47,0:00:01,40,7
|
||||||
|
10346,346 bottles of beer on the wall,Option 1,0.9305162979,28FEB1960,01JAN1960:09:46:40,0:00:59,56,28
|
||||||
|
10347,347 bottles of beer on the wall,Option 1,0.7591318552,18FEB1962,01JAN1960:13:25:32,0:01:10,41,9
|
||||||
|
10348,348 bottles of beer on the wall,Option 1,0.4177664911,11SEP1961,01JAN1960:09:55:17,0:01:39,76,82
|
||||||
|
10349,349 bottles of beer on the wall,Option 1,0.4690050443,05DEC1961,01JAN1960:11:05:15,0:01:09,63,40
|
||||||
|
10350,350 bottles of beer on the wall,Option 1,0.7541399979,31AUG1961,01JAN1960:12:30:45,0:00:33,57,12
|
||||||
|
10351,351 bottles of beer on the wall,Option 1,0.1392844325,17MAR1962,01JAN1960:08:20:38,0:00:41,85,45
|
||||||
|
10352,352 bottles of beer on the wall,Option 1,0.1020530235,23DEC1961,01JAN1960:09:46:20,0:00:01,55,56
|
||||||
|
10353,353 bottles of beer on the wall,Option 1,0.0257998794,04DEC1961,01JAN1960:09:47:10,0:00:31,100,2
|
||||||
|
10354,354 bottles of beer on the wall,Option 1,0.1238113316,20MAR1962,01JAN1960:09:15:30,0:00:01,74,11
|
||||||
|
10355,355 bottles of beer on the wall,Option 1,0.4214245292,24NOV1960,01JAN1960:04:24:09,0:01:01,79,83
|
||||||
|
10356,356 bottles of beer on the wall,Option 1,0.3243381057,12FEB1961,01JAN1960:00:55:59,0:00:50,30,52
|
||||||
|
10357,357 bottles of beer on the wall,Option 1,0.9735697345,24NOV1960,01JAN1960:07:10:56,0:01:33,64,2
|
||||||
|
10358,358 bottles of beer on the wall,Option 1,0.4796259461,28JAN1961,01JAN1960:11:51:29,0:01:03,19,29
|
||||||
|
10359,359 bottles of beer on the wall,Option 1,0.003359966,01SEP1960,01JAN1960:13:24:25,0:00:09,66,60
|
||||||
|
10360,360 bottles of beer on the wall,Option 1,0.5773700334,21JAN1960,01JAN1960:10:15:32,0:00:40,9,21
|
||||||
|
10361,361 bottles of beer on the wall,Option 1,0.0792848342,25JAN1962,01JAN1960:06:00:35,0:01:25,73,73
|
||||||
|
10362,362 bottles of beer on the wall,Option 1,0.9339359365,30MAY1961,01JAN1960:09:08:13,0:00:56,12,56
|
||||||
|
10363,363 bottles of beer on the wall,Option 1,0.3517632132,12FEB1961,01JAN1960:12:07:19,0:00:01,74,69
|
||||||
|
10364,364 bottles of beer on the wall,Option 1,0.4088954895,17MAR1961,01JAN1960:08:04:51,0:01:01,70,66
|
||||||
|
10365,365 bottles of beer on the wall,Option 1,0.1254259623,30DEC1961,01JAN1960:06:47:12,0:00:01,79,43
|
||||||
|
10366,366 bottles of beer on the wall,Option 1,0.9190132958,28MAY1961,01JAN1960:06:35:42,0:00:07,19,31
|
||||||
|
10367,367 bottles of beer on the wall,Option 1,0.3033860015,17MAY1962,01JAN1960:05:32:03,0:00:32,57,73
|
||||||
|
10368,368 bottles of beer on the wall,Option 1,0.1463442846,02SEP1962,01JAN1960:01:24:29,0:00:53,19,64
|
||||||
|
10369,369 bottles of beer on the wall,Option 1,0.5516236343,18JUN1962,01JAN1960:10:52:23,0:00:11,51,40
|
||||||
|
10370,370 bottles of beer on the wall,Option 1,0.5205378246,19JAN1960,01JAN1960:06:54:14,0:00:58,2,72
|
||||||
|
10371,371 bottles of beer on the wall,Option 1,0.9941610768,28MAR1962,01JAN1960:04:55:58,0:00:22,46,65
|
||||||
|
10372,372 bottles of beer on the wall,Option 1,0.065678,07MAY1961,01JAN1960:10:17:35,0:00:10,54,100
|
||||||
|
10373,373 bottles of beer on the wall,Option 1,0.7222646138,17JUL1961,01JAN1960:01:47:32,0:00:51,26,96
|
||||||
|
10374,374 bottles of beer on the wall,Option 1,0.8772228294,23JUL1960,01JAN1960:00:30:51,0:00:40,18,45
|
||||||
|
10375,375 bottles of beer on the wall,Option 1,0.3651081847,11DEC1961,01JAN1960:00:46:15,0:00:15,14,90
|
||||||
|
10376,376 bottles of beer on the wall,Option 1,0.3800431529,15AUG1960,01JAN1960:05:30:55,0:00:19,13,74
|
||||||
|
10377,377 bottles of beer on the wall,Option 1,0.1077003503,26FEB1960,01JAN1960:04:48:40,0:00:08,51,53
|
||||||
|
10378,378 bottles of beer on the wall,Option 1,0.7945664035,06MAR1961,01JAN1960:05:36:47,0:00:45,65,39
|
||||||
|
10379,379 bottles of beer on the wall,Option 1,0.8754883054,06JUN1960,01JAN1960:06:09:33,0:00:04,3,3
|
||||||
|
10380,380 bottles of beer on the wall,Option 1,0.9975561108,10AUG1960,01JAN1960:10:34:33,0:00:28,92,29
|
||||||
|
10381,381 bottles of beer on the wall,Option 1,0.9817031599,07JUL1960,01JAN1960:01:40:00,0:00:39,63,45
|
||||||
|
10382,382 bottles of beer on the wall,Option 1,0.4427802341,07JAN1962,01JAN1960:01:21:32,0:01:31,7,54
|
||||||
|
10383,383 bottles of beer on the wall,Option 1,0.03180474,17JUL1962,01JAN1960:07:15:54,0:01:08,72,60
|
||||||
|
10384,384 bottles of beer on the wall,Option 1,0.1031627707,10MAY1962,01JAN1960:02:52:58,0:01:31,6,64
|
||||||
|
10385,385 bottles of beer on the wall,Option 1,0.911744344,01MAY1960,01JAN1960:03:51:16,0:01:04,1,54
|
||||||
|
10386,386 bottles of beer on the wall,Option 1,0.4912374353,13FEB1961,01JAN1960:07:22:49,0:01:21,70,71
|
||||||
|
10387,387 bottles of beer on the wall,Option 1,0.8803869509,04JUL1960,01JAN1960:12:14:05,0:00:18,78,88
|
||||||
|
10388,388 bottles of beer on the wall,Option 1,0.0596609544,17DEC1960,01JAN1960:08:29:20,0:00:53,13,84
|
||||||
|
10389,389 bottles of beer on the wall,Option 1,0.6625022132,12JAN1961,01JAN1960:11:15:39,0:01:05,10,31
|
||||||
|
10390,390 bottles of beer on the wall,Option 1,0.2669677358,05OCT1961,01JAN1960:00:48:03,0:01:33,29,31
|
||||||
|
10391,391 bottles of beer on the wall,Option 1,0.8095563454,04DEC1961,01JAN1960:07:54:13,0:01:15,95,2
|
||||||
|
10392,392 bottles of beer on the wall,Option 1,0.6406704796,27JAN1961,01JAN1960:03:35:55,0:00:36,92,47
|
||||||
|
10393,393 bottles of beer on the wall,Option 1,0.2188341847,02MAR1960,01JAN1960:04:05:21,0:00:11,28,34
|
||||||
|
10394,394 bottles of beer on the wall,Option 1,0.7052043424,09JUN1962,01JAN1960:07:00:21,0:01:14,84,19
|
||||||
|
10395,395 bottles of beer on the wall,Option 1,0.9843204464,18APR1960,01JAN1960:04:54:31,0:01:29,46,46
|
||||||
|
10396,396 bottles of beer on the wall,Option 1,0.329249541,10SEP1961,01JAN1960:13:21:04,0:00:21,70,11
|
||||||
|
10397,397 bottles of beer on the wall,Option 1,0.2073628675,13JUL1962,01JAN1960:11:16:26,0:01:23,17,97
|
||||||
|
10398,398 bottles of beer on the wall,Option 1,0.7881676665,29JUN1962,01JAN1960:11:36:47,0:00:50,39,72
|
||||||
|
10399,399 bottles of beer on the wall,Option 1,0.4347905537,31AUG1962,01JAN1960:02:30:30,0:00:21,86,61
|
||||||
|
10400,400 bottles of beer on the wall,Option 1,0.2937454084,05APR1962,01JAN1960:02:44:06,0:00:32,27,81
|
||||||
|
10401,401 bottles of beer on the wall,Option 1,0.6659902565,10APR1961,01JAN1960:11:53:59,0:00:01,80,17
|
||||||
|
10402,402 bottles of beer on the wall,Option 1,0.7637229686,07APR1962,01JAN1960:05:45:25,0:01:28,11,17
|
||||||
|
10403,403 bottles of beer on the wall,Option 1,0.3325480941,19MAR1961,01JAN1960:09:57:05,0:00:27,9,99
|
||||||
|
10404,404 bottles of beer on the wall,Option 1,0.580015553,10AUG1960,01JAN1960:06:15:44,0:00:25,27,99
|
||||||
|
10405,405 bottles of beer on the wall,Option 1,0.2514696071,08APR1961,01JAN1960:10:37:45,0:00:17,29,59
|
||||||
|
10406,406 bottles of beer on the wall,Option 1,0.3792107284,19MAR1962,01JAN1960:04:49:30,0:00:07,44,38
|
||||||
|
10407,407 bottles of beer on the wall,Option 1,0.4702913125,13DEC1961,01JAN1960:09:03:31,0:00:38,95,90
|
||||||
|
10408,408 bottles of beer on the wall,Option 1,0.4207190659,03FEB1961,01JAN1960:00:37:47,0:00:38,37,65
|
||||||
|
10409,409 bottles of beer on the wall,Option 1,0.2485069117,08DEC1961,01JAN1960:07:18:28,0:01:39,91,64
|
||||||
|
10410,410 bottles of beer on the wall,Option 1,0.3257893502,27NOV1961,01JAN1960:11:33:02,0:00:54,41,7
|
||||||
|
10411,411 bottles of beer on the wall,Option 1,0.0967283533,11AUG1962,01JAN1960:07:23:15,0:00:21,90,1
|
||||||
|
10412,412 bottles of beer on the wall,Option 1,0.532676542,01SEP1960,01JAN1960:02:46:29,0:00:45,31,48
|
||||||
|
10413,413 bottles of beer on the wall,Option 1,0.2564602151,15JAN1961,01JAN1960:01:09:11,0:01:21,16,89
|
||||||
|
10414,414 bottles of beer on the wall,Option 1,0.0865634024,20MAR1962,01JAN1960:12:56:45,0:00:05,75,51
|
||||||
|
10415,415 bottles of beer on the wall,Option 1,0.2926342321,07FEB1960,01JAN1960:06:48:55,0:00:36,66,33
|
||||||
|
10416,416 bottles of beer on the wall,Option 1,0.0678594029,06OCT1961,01JAN1960:07:14:58,0:01:26,50,16
|
||||||
|
10417,417 bottles of beer on the wall,Option 1,0.6376664767,09JUN1960,01JAN1960:05:00:13,0:01:37,7,92
|
||||||
|
10418,418 bottles of beer on the wall,Option 1,0.4795483525,14JUN1962,01JAN1960:00:00:50,0:00:50,33,74
|
||||||
|
10419,419 bottles of beer on the wall,Option 1,0.3492934342,22MAR1960,01JAN1960:08:54:52,0:01:26,61,72
|
||||||
|
10420,420 bottles of beer on the wall,Option 1,0.5085071356,14MAR1960,01JAN1960:09:47:51,0:00:56,36,63
|
||||||
|
10421,421 bottles of beer on the wall,Option 1,0.414953564,25MAR1961,01JAN1960:03:35:19,0:00:30,47,30
|
||||||
|
10422,422 bottles of beer on the wall,Option 1,0.2431976652,25SEP1960,01JAN1960:08:47:25,0:00:17,6,42
|
||||||
|
10423,423 bottles of beer on the wall,Option 1,0.2370444998,04MAR1962,01JAN1960:00:16:44,0:01:36,54,100
|
||||||
|
10424,424 bottles of beer on the wall,Option 1,0.8687893324,12OCT1961,01JAN1960:03:16:33,0:00:56,97,25
|
||||||
|
10425,425 bottles of beer on the wall,Option 1,0.0470510335,10MAY1960,01JAN1960:02:44:07,0:01:05,83,59
|
||||||
|
10426,426 bottles of beer on the wall,Option 1,0.7114342887,12APR1960,01JAN1960:02:17:40,0:00:39,57,97
|
||||||
|
10427,427 bottles of beer on the wall,Option 1,0.6176668283,05JUL1962,01JAN1960:09:09:12,0:01:03,92,38
|
||||||
|
10428,428 bottles of beer on the wall,Option 1,0.0657907743,01JUL1962,01JAN1960:11:03:37,0:01:35,97,63
|
||||||
|
10429,429 bottles of beer on the wall,Option 1,0.280104912,13MAR1962,01JAN1960:10:35:08,0:01:07,42,35
|
||||||
|
10430,430 bottles of beer on the wall,Option 1,0.3639827088,02APR1960,01JAN1960:12:00:50,0:00:40,91,84
|
||||||
|
10431,431 bottles of beer on the wall,Option 1,0.2130561137,25AUG1961,01JAN1960:12:07:22,0:01:37,70,9
|
||||||
|
10432,432 bottles of beer on the wall,Option 1,0.9656705889,23DEC1960,01JAN1960:02:36:48,0:01:28,23,92
|
||||||
|
10433,433 bottles of beer on the wall,Option 1,0.5824601052,22JAN1961,01JAN1960:01:19:48,0:00:32,73,6
|
||||||
|
10434,434 bottles of beer on the wall,Option 1,0.5207124942,23APR1961,01JAN1960:10:45:16,0:01:08,45,85
|
||||||
|
10435,435 bottles of beer on the wall,Option 1,0.9280530661,01NOV1960,01JAN1960:12:46:59,0:01:36,57,4
|
||||||
|
10436,436 bottles of beer on the wall,Option 1,0.8982810149,29NOV1961,01JAN1960:09:23:13,0:01:15,100,68
|
||||||
|
10437,437 bottles of beer on the wall,Option 1,0.3268259467,04MAR1960,01JAN1960:01:22:42,0:00:04,99,61
|
||||||
|
10438,438 bottles of beer on the wall,Option 1,0.2038002704,12FEB1962,01JAN1960:09:03:24,0:00:40,97,78
|
||||||
|
10439,439 bottles of beer on the wall,Option 1,0.0798850833,11MAY1960,01JAN1960:00:32:50,0:00:37,7,49
|
||||||
|
10440,440 bottles of beer on the wall,Option 1,0.6697000566,01SEP1960,01JAN1960:08:04:03,0:00:30,7,68
|
||||||
|
10441,441 bottles of beer on the wall,Option 1,0.550699767,11JAN1960,01JAN1960:06:33:15,0:01:09,19,10
|
||||||
|
10442,442 bottles of beer on the wall,Option 1,0.9514032798,07FEB1962,01JAN1960:06:03:16,0:01:13,65,87
|
||||||
|
10443,443 bottles of beer on the wall,Option 1,0.1182718324,08FEB1960,01JAN1960:11:28:52,0:00:46,61,59
|
||||||
|
10444,444 bottles of beer on the wall,Option 1,0.5772118874,11FEB1962,01JAN1960:01:14:29,0:01:07,16,22
|
||||||
|
10445,445 bottles of beer on the wall,Option 1,0.9828714463,06DEC1960,01JAN1960:05:47:08,0:01:40,66,4
|
||||||
|
10446,446 bottles of beer on the wall,Option 1,0.1229167269,02JUN1960,01JAN1960:09:43:51,0:01:34,29,24
|
||||||
|
10447,447 bottles of beer on the wall,Option 1,0.2102257522,09MAR1961,01JAN1960:04:06:09,0:01:27,53,78
|
||||||
|
10448,448 bottles of beer on the wall,Option 1,0.9958884935,20FEB1962,01JAN1960:06:43:53,0:00:07,42,65
|
||||||
|
10449,449 bottles of beer on the wall,Option 1,0.3530408085,04MAY1961,01JAN1960:11:26:59,0:01:37,76,35
|
||||||
|
10450,450 bottles of beer on the wall,Option 1,0.2848354258,03SEP1960,01JAN1960:13:26:36,0:00:25,69,38
|
||||||
|
10451,451 bottles of beer on the wall,Option 1,0.1461860818,10JUN1960,01JAN1960:01:24:25,0:00:02,61,23
|
||||||
|
10452,452 bottles of beer on the wall,Option 1,0.2033735766,29AUG1960,01JAN1960:12:30:17,0:00:19,32,75
|
||||||
|
10453,453 bottles of beer on the wall,Option 1,0.7973149958,26JUN1961,01JAN1960:04:46:06,0:00:21,94,14
|
||||||
|
10454,454 bottles of beer on the wall,Option 1,0.6812086425,07NOV1961,01JAN1960:01:59:51,0:00:12,89,59
|
||||||
|
10455,455 bottles of beer on the wall,Option 1,0.6111464974,24FEB1962,01JAN1960:07:42:56,0:00:15,23,92
|
||||||
|
10456,456 bottles of beer on the wall,Option 1,0.9542484209,09APR1961,01JAN1960:09:09:17,0:01:26,87,93
|
||||||
|
10457,457 bottles of beer on the wall,Option 1,0.9818577077,18AUG1960,01JAN1960:12:24:47,0:01:08,18,20
|
||||||
|
10458,458 bottles of beer on the wall,Option 1,0.9331120881,06JUL1961,01JAN1960:10:10:02,0:01:40,78,36
|
||||||
|
10459,459 bottles of beer on the wall,Option 1,0.8953045587,22APR1960,01JAN1960:04:47:34,0:00:37,13,46
|
||||||
|
10460,460 bottles of beer on the wall,Option 1,0.1584420461,08JAN1961,01JAN1960:07:47:49,0:00:05,85,61
|
||||||
|
10461,461 bottles of beer on the wall,Option 1,0.9324573814,24DEC1960,01JAN1960:02:13:36,0:00:22,55,94
|
||||||
|
10462,462 bottles of beer on the wall,Option 1,0.0813189871,21AUG1961,01JAN1960:09:18:28,0:00:36,42,49
|
||||||
|
10463,463 bottles of beer on the wall,Option 1,0.8736312594,17MAY1962,01JAN1960:12:52:58,0:00:30,45,7
|
||||||
|
10464,464 bottles of beer on the wall,Option 1,0.1894013794,06NOV1960,01JAN1960:12:56:13,0:01:30,11,50
|
||||||
|
10465,465 bottles of beer on the wall,Option 1,0.9149773772,07JUN1960,01JAN1960:08:53:28,0:00:22,23,17
|
||||||
|
10466,466 bottles of beer on the wall,Option 1,0.6329479598,27JUN1962,01JAN1960:07:38:23,0:00:06,68,14
|
||||||
|
10467,467 bottles of beer on the wall,Option 1,0.1897066413,21AUG1961,01JAN1960:10:15:28,0:01:12,59,46
|
||||||
|
10468,468 bottles of beer on the wall,Option 1,0.8352205767,16MAR1961,01JAN1960:06:48:50,0:00:44,60,37
|
||||||
|
10469,469 bottles of beer on the wall,Option 1,0.3339443432,09OCT1960,01JAN1960:00:52:53,0:00:27,70,44
|
||||||
|
10470,470 bottles of beer on the wall,Option 1,0.1096137567,09JUL1962,01JAN1960:08:28:10,0:01:15,88,81
|
||||||
|
10471,471 bottles of beer on the wall,Option 1,0.1481936733,10JAN1962,01JAN1960:06:38:41,0:00:56,21,77
|
||||||
|
10472,472 bottles of beer on the wall,Option 1,0.5630390432,01MAR1960,01JAN1960:06:35:09,0:01:08,70,32
|
||||||
|
10473,473 bottles of beer on the wall,Option 1,0.0604085713,12APR1962,01JAN1960:02:41:26,0:00:46,36,17
|
||||||
|
10474,474 bottles of beer on the wall,Option 1,0.6011423606,25DEC1961,01JAN1960:02:57:45,0:01:11,36,18
|
||||||
|
10475,475 bottles of beer on the wall,Option 1,0.7698335782,31JUL1962,01JAN1960:07:46:29,0:01:34,72,17
|
||||||
|
10476,476 bottles of beer on the wall,Option 1,0.3823641224,17MAR1962,01JAN1960:03:34:37,0:00:09,27,86
|
||||||
|
10477,477 bottles of beer on the wall,Option 1,0.9225378446,12JAN1962,01JAN1960:08:41:25,0:01:06,45,20
|
||||||
|
10478,478 bottles of beer on the wall,Option 1,0.2979750453,23JUN1962,01JAN1960:10:06:36,0:01:28,88,7
|
||||||
|
10479,479 bottles of beer on the wall,Option 1,0.4988665942,15JUL1961,01JAN1960:02:33:06,0:01:33,85,1
|
||||||
|
10480,480 bottles of beer on the wall,Option 1,0.5243853585,29JUL1960,01JAN1960:00:26:18,0:00:31,48,77
|
||||||
|
10481,481 bottles of beer on the wall,Option 1,0.6049248826,12JUL1962,01JAN1960:10:01:41,0:00:16,66,45
|
||||||
|
10482,482 bottles of beer on the wall,Option 1,0.6312438024,01OCT1961,01JAN1960:05:18:12,0:00:04,43,27
|
||||||
|
10483,483 bottles of beer on the wall,Option 1,0.3366865974,17MAY1962,01JAN1960:01:44:17,0:00:01,31,25
|
||||||
|
10484,484 bottles of beer on the wall,Option 1,0.0813266188,08AUG1962,01JAN1960:06:18:27,0:00:08,71,63
|
||||||
|
10485,485 bottles of beer on the wall,Option 1,0.3601163455,23JAN1962,01JAN1960:11:26:01,0:00:37,41,88
|
||||||
|
10486,486 bottles of beer on the wall,Option 1,0.9033777345,13AUG1961,01JAN1960:00:16:14,0:00:56,82,33
|
||||||
|
10487,487 bottles of beer on the wall,Option 1,0.1716986667,23DEC1960,01JAN1960:12:06:34,0:01:13,2,32
|
||||||
|
10488,488 bottles of beer on the wall,Option 1,0.9734818912,11SEP1961,01JAN1960:00:34:41,0:00:28,17,7
|
||||||
|
10489,489 bottles of beer on the wall,Option 1,0.0618140223,17DEC1961,01JAN1960:06:26:30,0:00:38,94,40
|
||||||
|
10490,490 bottles of beer on the wall,Option 1,0.0204490144,22AUG1960,01JAN1960:01:50:18,0:00:19,40,56
|
||||||
|
10491,491 bottles of beer on the wall,Option 1,0.8719323929,23MAY1960,01JAN1960:12:36:06,0:00:08,49,44
|
||||||
|
10492,492 bottles of beer on the wall,Option 1,0.2656292181,28JUN1962,01JAN1960:05:32:50,0:01:35,15,39
|
||||||
|
10493,493 bottles of beer on the wall,Option 1,0.37794835,23JUL1962,01JAN1960:13:15:43,0:00:56,6,86
|
||||||
|
10494,494 bottles of beer on the wall,Option 1,0.6395865733,17JAN1961,01JAN1960:12:20:12,0:01:31,22,87
|
||||||
|
10495,495 bottles of beer on the wall,Option 1,0.4408595098,05JUL1960,01JAN1960:12:21:53,0:01:40,25,27
|
||||||
|
10496,496 bottles of beer on the wall,Option 1,0.4846261169,02DEC1961,01JAN1960:12:41:08,0:00:06,7,63
|
||||||
|
10497,497 bottles of beer on the wall,Option 1,0.7903671478,14MAY1962,01JAN1960:05:09:21,0:01:03,98,25
|
||||||
|
10498,498 bottles of beer on the wall,Option 1,0.60474184,13OCT1961,01JAN1960:03:52:59,0:01:22,98,98
|
||||||
|
10499,499 bottles of beer on the wall,Option 1,0.1213259218,23APR1962,01JAN1960:06:29:47,0:01:35,38,70
|
||||||
|
10500,500 bottles of beer on the wall,Option 1,0.7882370487,17FEB1962,01JAN1960:02:00:25,0:00:12,1,74
|
|
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx
Normal file
Binary file not shown.
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx
Normal file
Binary file not shown.
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx
Normal file
Binary file not shown.
@ -15,9 +15,6 @@ context('editor tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -118,10 +115,6 @@ context('editor tests: ', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const clickOnEdit = (callback?: any) => {
|
const clickOnEdit = (callback?: any) => {
|
||||||
@ -221,14 +214,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
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@ context('excel tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
|
|
||||||
@ -339,7 +336,6 @@ context('excel tests: ', function () {
|
|||||||
|
|
||||||
this.afterEach(() => {
|
this.afterEach(() => {
|
||||||
colorLog(`TEST END -------------`, '#3498DB')
|
colorLog(`TEST END -------------`, '#3498DB')
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -407,14 +403,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 +432,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
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,6 @@ context('filtering tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation, { timeout: longerCommandTimeout })
|
cy.visit(hostUrl + appLocation, { timeout: longerCommandTimeout })
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -173,10 +170,6 @@ context('filtering tests: ', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkInfoBarIncludes = (text: string, callback: any) => {
|
const checkInfoBarIncludes = (text: string, callback: any) => {
|
||||||
|
@ -23,15 +23,11 @@ interface EditConfigTableCells {
|
|||||||
|
|
||||||
context('licensing tests: ', function () {
|
context('licensing tests: ', function () {
|
||||||
this.beforeAll(() => {
|
this.beforeAll(() => {
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
cy.loginAndUpdateValidKey()
|
cy.loginAndUpdateValidKey()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
@ -374,10 +370,6 @@ context('licensing tests: ', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const logout = (callback?: any) => {
|
const logout = (callback?: any) => {
|
||||||
@ -699,14 +691,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
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,6 @@ context('liveness tests: ', function () {
|
|||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
// cy.get('input.username').type(username)
|
|
||||||
// cy.get('input.password').type(password)
|
|
||||||
// cy.get('.login-group button').click()
|
|
||||||
|
|
||||||
visitPage('home')
|
visitPage('home')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -125,14 +121,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
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ context('editor tests: ', function () {
|
|||||||
|
|
||||||
this.beforeEach(() => {
|
this.beforeEach(() => {
|
||||||
cy.visit(hostUrl + appLocation)
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
cy.wait(2000)
|
cy.wait(2000)
|
||||||
|
|
||||||
cy.get('body').then(($body) => {
|
cy.get('body').then(($body) => {
|
||||||
@ -386,10 +385,6 @@ context('editor tests: ', function () {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.afterEach(() => {
|
|
||||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkColumns = (columns: string[], callback: () => void) => {
|
const checkColumns = (columns: string[], callback: () => void) => {
|
||||||
|
@ -6,5 +6,8 @@
|
|||||||
"lib": ["es2019", "dom"],
|
"lib": ["es2019", "dom"],
|
||||||
"types": ["cypress", "cypress-real-events"]
|
"types": ["cypress", "cypress-real-events"]
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts"]
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
"../cypress.config.ts"
|
||||||
|
]
|
||||||
}
|
}
|
BIN
client/libraries/clr-angular-17.9.0.tgz
Normal file
BIN
client/libraries/clr-angular-17.9.0.tgz
Normal file
Binary file not shown.
BIN
client/libraries/clr-ui-17.9.0.tgz
Normal file
BIN
client/libraries/clr-ui-17.9.0.tgz
Normal file
Binary file not shown.
BIN
client/libraries/sheet-crypto.tgz.gpg
Normal file
BIN
client/libraries/sheet-crypto.tgz.gpg
Normal file
Binary file not shown.
@ -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.1.0;handsontable@13.1.0;hyperformula@2.5.0;jackspeak@2.2.0;path-scurry@1.7.0'
|
'@cds/city@1.1.0;@handsontable/angular@15.3.0;handsontable@15.3.0;hyperformula@2.7.1;hyperformula@3.0.0;jackspeak@3.4.3;path-scurry@1.11.1;package-json-from-dist@1.0.1'
|
||||||
},
|
},
|
||||||
(error, json) => {
|
(error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
31102
client/package-lock.json
generated
31102
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||||
@ -35,32 +35,32 @@
|
|||||||
},
|
},
|
||||||
"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.15.1",
|
||||||
"@clr/angular": "^13.17.0",
|
"@clr/angular": "file:libraries/clr-angular-17.9.0.tgz",
|
||||||
"@clr/icons": "^13.0.2",
|
"@clr/icons": "^13.0.2",
|
||||||
"@clr/ui": "^13.17.0",
|
"@clr/ui": "file:libraries/clr-ui-17.9.0.tgz",
|
||||||
"@handsontable/angular": "^13.1.0",
|
"@handsontable/angular": "^15.3.0",
|
||||||
"@sasjs/adapter": "4.10.1",
|
"@sasjs/adapter": "^4.11.0",
|
||||||
"@sasjs/utils": "^3.4.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",
|
||||||
"@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.1",
|
||||||
"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.1.0",
|
"handsontable": "^15.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",
|
||||||
@ -78,24 +78,27 @@
|
|||||||
"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",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
|
"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",
|
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
||||||
"@compodoc/compodoc": "^1.1.21",
|
"@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",
|
||||||
@ -109,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",
|
||||||
@ -123,9 +126,7 @@
|
|||||||
"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.24.8",
|
"typescript": "~5.4.4",
|
||||||
"typedoc-plugin-external-module-name": "^4.0.6",
|
|
||||||
"typescript": "~4.9.4",
|
|
||||||
"wait-on": "^6.0.1",
|
"wait-on": "^6.0.1",
|
||||||
"watch": "^1.0.2"
|
"watch": "^1.0.2"
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,16 @@ export const initFilter: { filter: FilterCache } = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface XLMapListItem {
|
||||||
|
id: string
|
||||||
|
description: string
|
||||||
|
targetDS: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandsontableStaticConfig {
|
||||||
|
darkTableHeaderClass: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached filtering values across whole app (editor, viewer, viewboxes)
|
* Cached filtering values across whole app (editor, viewer, viewboxes)
|
||||||
* Cached lineage libraries, tables
|
* Cached lineage libraries, tables
|
||||||
@ -46,6 +56,8 @@ export const initFilter: { filter: FilterCache } = {
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
@ -54,14 +66,17 @@ export const globals: {
|
|||||||
viyaApi: any
|
viyaApi: any
|
||||||
usernav: any
|
usernav: any
|
||||||
operators: any
|
operators: any
|
||||||
|
handsontable: HandsontableStaticConfig
|
||||||
[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>{
|
||||||
@ -130,5 +145,11 @@ export const globals: {
|
|||||||
operators: {
|
operators: {
|
||||||
numOperators: ['=', '<', '>', '<=', '>=', 'BETWEEN', 'IN', 'NOT IN', 'NE'],
|
numOperators: ['=', '<', '>', '<=', '>=', 'BETWEEN', 'IN', 'NOT IN', 'NE'],
|
||||||
charOperators: ['=', '<', '>', '<=', '>=', 'CONTAINS', 'IN', 'NOT IN', 'NE']
|
charOperators: ['=', '<', '>', '<=', '>=', 'CONTAINS', 'IN', 'NOT IN', 'NE']
|
||||||
|
},
|
||||||
|
handsontable: {
|
||||||
|
darkTableHeaderClass: 'darkTH'
|
||||||
|
},
|
||||||
|
userDropdownConfig: {
|
||||||
|
closeOnDebugClick: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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">
|
||||||
@ -139,10 +139,15 @@
|
|||||||
[routerLink]="['/']"
|
[routerLink]="['/']"
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
>
|
>
|
||||||
<img class="without-text d-block d-md-none" src="images/dc-logo.svg" />
|
<img
|
||||||
|
class="without-text d-block d-md-none"
|
||||||
|
src="images/dc-logo.svg"
|
||||||
|
alt="datacontroller logo without text"
|
||||||
|
/>
|
||||||
<img
|
<img
|
||||||
class="with-text d-none d-md-block"
|
class="with-text d-none d-md-block"
|
||||||
src="images/datacontroller.svg"
|
src="images/datacontroller.svg"
|
||||||
|
alt="datacontroller logo"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -168,7 +173,7 @@
|
|||||||
</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]="['/review/submitted']" clrDropdownItem>REVIEW</a>
|
<a [routerLink]="['/review/submitted']" clrDropdownItem>REVIEW</a>
|
||||||
</clr-dropdown-menu>
|
</clr-dropdown-menu>
|
||||||
</clr-dropdown>
|
</clr-dropdown>
|
||||||
@ -189,7 +194,7 @@
|
|||||||
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]="['/review/submitted']"
|
[routerLink]="['/review/submitted']"
|
||||||
@ -204,14 +209,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="
|
||||||
@ -252,6 +250,7 @@
|
|||||||
|
|
||||||
<app-alerts *ngIf="!errTop"></app-alerts>
|
<app-alerts *ngIf="!errTop"></app-alerts>
|
||||||
<app-requests-modal [(opened)]="requestsModal"></app-requests-modal>
|
<app-requests-modal [(opened)]="requestsModal"></app-requests-modal>
|
||||||
|
<app-excel-password-modal></app-excel-password-modal>
|
||||||
|
|
||||||
<!-- <app-terms *ngIf="showRegistration"></app-terms> -->
|
<!-- <app-terms *ngIf="showRegistration"></app-terms> -->
|
||||||
|
|
||||||
@ -289,7 +288,11 @@
|
|||||||
|
|
||||||
<!-- App Loading Page -->
|
<!-- App Loading Page -->
|
||||||
<div *ngIf="!startupDataLoaded" class="app-loading">
|
<div *ngIf="!startupDataLoaded" class="app-loading">
|
||||||
<img class="loading-logo" src="images/datacontroller.svg" />
|
<img
|
||||||
|
class="loading-logo"
|
||||||
|
src="images/datacontroller.svg"
|
||||||
|
alt="datacontroller logo"
|
||||||
|
/>
|
||||||
|
|
||||||
<div *ngIf="appActive === null" class="slider">
|
<div *ngIf="appActive === null" class="slider">
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
|
@ -1,461 +0,0 @@
|
|||||||
// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
|
||||||
// This software is released under MIT license.
|
|
||||||
// The full license information can be found in LICENSE in the root directory of this project.
|
|
||||||
app-requests-modal {
|
|
||||||
z-index: 10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
header.app-header {
|
|
||||||
background: #314351 !important;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo img.without-text {
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo img.with-text {
|
|
||||||
width: 210px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-hamburger-trigger {
|
|
||||||
display: block;
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-expired-notice {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 100vh !important;
|
|
||||||
width: 100vw !important;
|
|
||||||
z-index: 105;
|
|
||||||
background: rgba(33, 33, 33, .5);
|
|
||||||
|
|
||||||
.expired-details {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 30px;
|
|
||||||
z-index: 110;
|
|
||||||
background: #314351;
|
|
||||||
|
|
||||||
.expired-notice {
|
|
||||||
color: #e0e0e0;
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
.mailto {
|
|
||||||
color: #8dc53e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container .update-key {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
color: white;
|
|
||||||
padding: 0px 10px;
|
|
||||||
background: #00000026;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-icon-wrapper {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-text {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-toggle {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 10px;
|
|
||||||
|
|
||||||
clr-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
.header-actions {
|
|
||||||
.dropdown {
|
|
||||||
position: unset; //without it, when opening user dropdown scrollbar was displaying without reason
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav
|
|
||||||
.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;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav .nav-link.active {
|
|
||||||
background: #61717D;
|
|
||||||
opacity: 1;
|
|
||||||
box-shadow: inset 0 -3px transparent;
|
|
||||||
// padding: 0 1rem 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav .nav-item {
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.notf {
|
|
||||||
background: #16a57a;
|
|
||||||
color: #fffcfc;
|
|
||||||
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 {
|
|
||||||
border-color: #61717D;
|
|
||||||
background-color: #61717D;
|
|
||||||
transition: .15s ease-in;
|
|
||||||
transition-property: border-color,background-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container {
|
|
||||||
min-height: 100vh !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container .content-container .content-area {
|
|
||||||
padding: 0rem 1rem 1rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-container {
|
|
||||||
z-index: 0!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navBarResp {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
background: #495A67;
|
|
||||||
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 {
|
|
||||||
.htInvalid {
|
|
||||||
background: black!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width:480px) {
|
|
||||||
h2 {
|
|
||||||
font-size: .7rem!important;
|
|
||||||
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-size: .7rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
padding: 0rem 1rem 0rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary .btn, .btn.btn-primary {
|
|
||||||
border-color: #314351;
|
|
||||||
background-color: #314351;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-appearance: none!important;
|
|
||||||
border-radius: .125rem;
|
|
||||||
border: 1px solid;
|
|
||||||
min-width: 3rem;
|
|
||||||
max-width: 15rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
text-align: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
letter-spacing: .12em;
|
|
||||||
font-size: .5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
height: 1.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 {
|
|
||||||
border-color: #314351;
|
|
||||||
background-color: #495A67;
|
|
||||||
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 {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
.htMobileEditorContainer .inputs textarea {
|
|
||||||
font-size: 13pt;
|
|
||||||
border: 2px solid #485967;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
box-shadow: none;
|
|
||||||
position: absolute;
|
|
||||||
left: 14px;
|
|
||||||
right: 0px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
padding: 7pt;
|
|
||||||
width: 290px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.htMobileEditorContainer .positionControls {
|
|
||||||
width: 333px;
|
|
||||||
position: absolute;
|
|
||||||
right: 5pt;
|
|
||||||
top: 50px;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.htMobileEditorContainer.active {
|
|
||||||
display: block;
|
|
||||||
height: 120px;
|
|
||||||
width: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handsontable {
|
|
||||||
background-color: #ffffff;
|
|
||||||
// border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
.handsontable th {
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Left and right */
|
|
||||||
.ht_clone_left th {
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Column headers */
|
|
||||||
.ht_clone_top th {
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ht_clone_top_left_corner th {
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ht_master tr:nth-of-type(odd) > td {
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
border: 1px solid rgb(197, 197, 197);
|
|
||||||
border-bottom: 1px solid rgb(236, 235, 235);
|
|
||||||
// padding: 1px 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ht_master tr:nth-of-type(even) > td {
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid rgb(197, 197, 197);
|
|
||||||
border-bottom: 1px solid rgb(236, 235, 235);
|
|
||||||
// padding: 1px 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wtBorder {
|
|
||||||
background-color: #495A67!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handsontable .handsontable.ht_clone_top .wtHider {
|
|
||||||
padding: 0 0 0px 0!important;
|
|
||||||
margin: 0px;
|
|
||||||
border-bottom: 3px solid #d6d3d3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-container {
|
|
||||||
background: #F5F6FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
box-shadow: 0 0.125rem 0 0 #d7d7d7;
|
|
||||||
border-radius: .0rem;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
// min-height: calc(100vh - 150px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.datagrid-compact, .datagrid-history{
|
|
||||||
.datagrid {
|
|
||||||
border-collapse: separate;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: .125rem;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #565656;
|
|
||||||
margin: 0;
|
|
||||||
margin-top: 1rem;
|
|
||||||
max-width: 100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 15px 15px 50px 15px;
|
|
||||||
}
|
|
||||||
.datagrid-foot {
|
|
||||||
-webkit-box-pack: end;
|
|
||||||
-ms-flex-pack: end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
height: 1.5rem;
|
|
||||||
padding: 0 .5rem;
|
|
||||||
line-height: calc(1.5rem - 3px);
|
|
||||||
font-size: .45833rem;
|
|
||||||
background-color: #fff;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
border-radius: 0px;
|
|
||||||
// border-radius: 0 0 .125rem .125rem;
|
|
||||||
}
|
|
||||||
.datagrid-footer {
|
|
||||||
position: absolute;
|
|
||||||
right: 15px;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
.datagrid .datagrid-head {
|
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
margin-top: .083333rem;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-box-direction: normal;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
background: #f5f6ff;
|
|
||||||
padding: .5rem 0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
box-shadow: 0 1px 0.125rem hsla(0,0%,45%,.25);
|
|
||||||
min-width: 5rem;
|
|
||||||
max-width: 15rem;
|
|
||||||
border-radius: .125rem;
|
|
||||||
visibility: hidden;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
|
||||||
border-collapse: separate;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: 0px;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #565656;
|
|
||||||
margin: 0;
|
|
||||||
margin-top: 1rem;
|
|
||||||
max-width: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th {
|
|
||||||
font-size: .45833rem;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: .03em;
|
|
||||||
background-color: #fff;
|
|
||||||
vertical-align: bottom;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header {
|
|
||||||
border-bottom: 2px solid #e4e4e4;
|
|
||||||
padding: 0 0 .5rem 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container .content-container {
|
|
||||||
min-height: 0px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-loading {
|
|
||||||
.loading-logo {
|
|
||||||
max-width: 400px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,9 @@
|
|||||||
import { ChangeDetectorRef, Component, ElementRef } from '@angular/core'
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { VERSION } from '../environments/version'
|
import { VERSION } from '../environments/version'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
@ -13,11 +18,31 @@ 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,
|
||||||
|
processOnVmIcon,
|
||||||
|
sunIcon,
|
||||||
|
tableIcon,
|
||||||
|
trashIcon
|
||||||
|
} from '@cds/core/icon'
|
||||||
|
|
||||||
|
ClarityIcons.addIcons(
|
||||||
|
moonIcon,
|
||||||
|
sunIcon,
|
||||||
|
exclamationTriangleIcon,
|
||||||
|
tableIcon,
|
||||||
|
trashIcon,
|
||||||
|
processOnVmIcon
|
||||||
|
)
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
private dcAdapterSettings: DcAdapterSettings | undefined
|
private dcAdapterSettings: DcAdapterSettings | undefined
|
||||||
|
@ -20,10 +20,10 @@ import { UsernavRouteComponent } from './routes/usernav-route/usernav-route.comp
|
|||||||
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 { HomeModule } from './home/home.module'
|
|
||||||
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: [
|
||||||
@ -46,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, LicensingGuard],
|
providers: [AppService, SasStoreService, LicensingGuard, AppSettingsService],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@ -4,19 +4,19 @@
|
|||||||
* 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 { NotFoundComponent } from './not-found/not-found.component'
|
import { NotFoundComponent } from './not-found/not-found.component'
|
||||||
|
|
||||||
|
import { DeployModule } from './deploy/deploy.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 { ReviewRouteComponent } from './routes/review-route/review-route.component'
|
||||||
import { StageModule } from './stage/stage.module'
|
import { StageModule } from './stage/stage.module'
|
||||||
import { EditorModule } from './editor/editor.module'
|
|
||||||
import { ViewerModule } from './viewer/viewer.module'
|
|
||||||
import { ReviewModule } from './review/review.module'
|
|
||||||
import { DeployModule } from './deploy/deploy.module'
|
|
||||||
import { LicensingModule } from './licensing/licensing.module'
|
|
||||||
import { SystemModule } from './system/system.module'
|
import { SystemModule } from './system/system.module'
|
||||||
|
import { ViewerModule } from './viewer/viewer.module'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defining routes
|
* Defining routes
|
||||||
@ -45,7 +45,10 @@ export const ROUTES: Routes = [
|
|||||||
path: 'licensing',
|
path: 'licensing',
|
||||||
loadChildren: () => LicensingModule
|
loadChildren: () => LicensingModule
|
||||||
},
|
},
|
||||||
{ path: 'home', component: HomeComponent },
|
{
|
||||||
|
path: 'home',
|
||||||
|
loadChildren: () => HomeModule
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Load editor module with subroutes
|
* Load editor module with subroutes
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="card-header">Terms and Conditions</div>
|
<div class="card-header">Terms and Conditions</div>
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="card-text">
|
<div class="card-text">
|
||||||
<p>
|
<p class="mt-0">
|
||||||
The Demo version of Data Controller is free for EVALUATION purposes
|
The Demo version of Data Controller is free for EVALUATION purposes
|
||||||
only. Before proceeding with configuration, please confirm that you
|
only. Before proceeding with configuration, please confirm that you
|
||||||
have read, understood, and agreed to the
|
have read, understood, and agreed to the
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
.card {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.log-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
background: #f0f0f0;
|
|
||||||
border: 1px solid #c9c9c9;
|
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#contexts-btn {
|
|
||||||
padding: 0;
|
|
||||||
min-width: 30px;
|
|
||||||
margin-left: 10px;
|
|
||||||
height: 30px;
|
|
||||||
display: inline-flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.validation-bar {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 20px;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
clr-icon {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.autodeploy-section {
|
|
||||||
padding: 0px 15px;
|
|
||||||
|
|
||||||
.clr-checkbox-wrapper {
|
|
||||||
margin: 20px 0 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-autodeploy {
|
|
||||||
display: block;
|
|
||||||
margin: 15px 0 15px 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
|
||||||
import { SasService } from '../services/sas.service'
|
import { SasService } from '../services/sas.service'
|
||||||
import { SASjsConfig } from '@sasjs/adapter'
|
import { SASjsConfig } from '@sasjs/adapter'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
@ -13,7 +13,8 @@ import { DcAdapterSettings } from '../models/DcAdapterSettings'
|
|||||||
styleUrls: ['./deploy.component.scss'],
|
styleUrls: ['./deploy.component.scss'],
|
||||||
host: {
|
host: {
|
||||||
class: 'content-container'
|
class: 'content-container'
|
||||||
}
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class DeployComponent implements OnInit {
|
export class DeployComponent implements OnInit {
|
||||||
public step: number = 0
|
public step: number = 0
|
||||||
@ -56,25 +57,6 @@ export class DeployComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.sasJsConfig.serverType === ServerType.SasViya) {
|
|
||||||
fetch('sasbuild/viya.json')
|
|
||||||
.then((res) => res.text())
|
|
||||||
.then((res) => {
|
|
||||||
let initJsonFile: any = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
initJsonFile = JSON.parse(res)
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initJsonFile) {
|
|
||||||
this.jsonFile = initJsonFile
|
|
||||||
this.loggerService.log(this.jsonFile)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setDeployDefaults()
|
this.setDeployDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,14 +9,17 @@
|
|||||||
<p class="m-0 align-self-start">Done</p>
|
<p class="m-0 align-self-start">Done</p>
|
||||||
<hr class="w-100" />
|
<hr class="w-100" />
|
||||||
|
|
||||||
<div class="deploy-status-row">
|
<div
|
||||||
|
*ngIf="autoDeployStatus.deployServicePack !== null"
|
||||||
|
class="deploy-status-row"
|
||||||
|
>
|
||||||
<clr-icon
|
<clr-icon
|
||||||
*ngIf="autoDeployStatus.deployServicePack"
|
*ngIf="autoDeployStatus.deployServicePack === true"
|
||||||
class="deploy-success"
|
class="deploy-success"
|
||||||
shape="success-standard"
|
shape="success-standard"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
<clr-icon
|
<clr-icon
|
||||||
*ngIf="!autoDeployStatus.deployServicePack"
|
*ngIf="!autoDeployStatus.deployServicePack === false"
|
||||||
class="deploy-error"
|
class="deploy-error"
|
||||||
shape="times-circle"
|
shape="times-circle"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
@ -52,7 +55,7 @@
|
|||||||
class="deploy-error"
|
class="deploy-error"
|
||||||
shape="times-circle"
|
shape="times-circle"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
LAUNCH / CONFIGURE
|
LAUNCH
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@ -94,20 +97,36 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="dcloc" class="mt-20 clr-control-label">DC Loc</label>
|
<label for="dcloc" class="mt-20 clr-control-label">DC Loc</label>
|
||||||
<div class="mb-10 clr-control-container">
|
<div class="mb-10 clr-control-container dc-loc-input-wrapper">
|
||||||
<div class="clr-input-wrapper">
|
<div class="clr-input-wrapper">
|
||||||
<p class="mt-0">{{ dcPath }}</p>
|
<input clrInput name="dcloc" [(ngModel)]="dcPath" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="dcloc" class="mt-20 clr-control-label">SAS Admin group</label>
|
<label for="dcloc" class="mt-20 clr-control-label">SAS Admin group</label>
|
||||||
<div class="mb-10 clr-control-container">
|
<div class="mb-10 clr-control-container">
|
||||||
<div class="clr-input-wrapper">
|
<div class="clr-input-wrapper">
|
||||||
<p class="mt-0">{{ selectedAdminGroup }}</p>
|
<select
|
||||||
|
*ngIf="!adminGroupsLoading"
|
||||||
|
clrSelect
|
||||||
|
name="options"
|
||||||
|
[(ngModel)]="selectedAdminGroup"
|
||||||
|
>
|
||||||
|
<option *ngFor="let adminGroup of adminGroups" [value]="adminGroup.id">
|
||||||
|
{{ adminGroup.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<clr-spinner
|
||||||
|
clrInline
|
||||||
|
class="spinner-sm"
|
||||||
|
*ngIf="adminGroupsLoading"
|
||||||
|
></clr-spinner>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<clr-checkbox-wrapper>
|
<!-- Keeping this for a reference in case future VIYA changes and starts allowing separate backend and frontend) -->
|
||||||
|
|
||||||
|
<!-- <clr-checkbox-wrapper>
|
||||||
<input
|
<input
|
||||||
clrCheckbox
|
clrCheckbox
|
||||||
[(ngModel)]="recreateDatabase"
|
[(ngModel)]="recreateDatabase"
|
||||||
@ -116,19 +135,28 @@
|
|||||||
checked
|
checked
|
||||||
/>
|
/>
|
||||||
<label>Recreate database</label>
|
<label>Recreate database</label>
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper> -->
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
(click)="runAutoDeploy()"
|
||||||
|
class="btn-autodeploy btn btn-primary d-inline-block mr-10"
|
||||||
|
>
|
||||||
|
Deploy
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Keeping this for a reference in case future VIYA changes and starts allowing separate backend and frontend) -->
|
||||||
|
|
||||||
|
<!-- <button
|
||||||
(click)="executeJson()"
|
(click)="executeJson()"
|
||||||
class="btn-autodeploy btn btn-primary d-inline-block mr-10"
|
class="btn-autodeploy btn btn-primary d-inline-block mr-10"
|
||||||
[disabled]="!jsonFile"
|
[disabled]="!jsonFile"
|
||||||
>
|
>
|
||||||
Deploy {{ !jsonFile ? '(json file is not available)' : '' }}
|
Deploy {{ !jsonFile ? '(json file is not available)' : '' }}
|
||||||
</button>
|
</button> -->
|
||||||
|
|
||||||
<button
|
<!-- <button
|
||||||
(click)="uploadJsonAuto.click()"
|
(click)="uploadJsonAuto.click()"
|
||||||
class="btn-autodeploy btn btn-primary d-inline-block mr-10"
|
class="btn-autodeploy btn btn-primary d-inline-block mr-10"
|
||||||
>
|
>
|
||||||
@ -140,7 +168,7 @@
|
|||||||
hidden
|
hidden
|
||||||
(click)="clearUploadInput($event)"
|
(click)="clearUploadInput($event)"
|
||||||
(change)="onJsonFileChange($event)"
|
(change)="onJsonFileChange($event)"
|
||||||
/>
|
/> -->
|
||||||
|
|
||||||
<clr-modal [(clrModalOpen)]="recreateDatabaseModal" [clrModalClosable]="false">
|
<clr-modal [(clrModalOpen)]="recreateDatabaseModal" [clrModalClosable]="false">
|
||||||
<h3 class="modal-title">Warning</h3>
|
<h3 class="modal-title">Warning</h3>
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
.auto-deploy {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.4);
|
|
||||||
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner-box {
|
|
||||||
width: 400px;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: #fff;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
box-shadow: 1px 1px 8px 0px #00000082;
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.deploy-status-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
align-self: flex-start;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0 0 0 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.deploy-success {
|
|
||||||
color: #6ECF44;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deploy-error {
|
|
||||||
color: #E74C3C;
|
|
||||||
// width: 20px;
|
|
||||||
// height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deploy-undeterminated {
|
|
||||||
color: #cacaca;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border: 0;
|
|
||||||
border-bottom: 1px solid #00000045;
|
|
||||||
}
|
|
@ -1,15 +1,28 @@
|
|||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
import {
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core'
|
||||||
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
||||||
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
||||||
import { DeployService } from 'src/app/services/deploy.service'
|
import { DeployService } from 'src/app/services/deploy.service'
|
||||||
import { EventService } from 'src/app/services/event.service'
|
import { EventService } from 'src/app/services/event.service'
|
||||||
import { LoggerService } from 'src/app/services/logger.service'
|
import { LoggerService } from 'src/app/services/logger.service'
|
||||||
|
import { SasViyaService } from 'src/app/services/sas-viya.service'
|
||||||
import { SasService } from 'src/app/services/sas.service'
|
import { SasService } from 'src/app/services/sas.service'
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ViyaApiIdentities
|
||||||
|
} from 'src/app/viya-api-explorer/models/viya-api-identities.model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-automatic-deploy',
|
selector: 'app-automatic-deploy',
|
||||||
templateUrl: './automatic.component.html',
|
templateUrl: './automatic.component.html',
|
||||||
styleUrls: ['./automatic.component.scss']
|
styleUrls: ['./automatic.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class AutomaticComponent implements OnInit {
|
export class AutomaticComponent implements OnInit {
|
||||||
@Input() sasJs!: SASjs
|
@Input() sasJs!: SASjs
|
||||||
@ -28,8 +41,14 @@ export class AutomaticComponent implements OnInit {
|
|||||||
public recreateDatabaseModal: boolean = false
|
public recreateDatabaseModal: boolean = false
|
||||||
public isSubmittingJson: boolean = false
|
public isSubmittingJson: boolean = false
|
||||||
public isJsonSubmitted: boolean = false
|
public isJsonSubmitted: boolean = false
|
||||||
public recreateDatabase: boolean = false
|
/**
|
||||||
|
* Default was `false` when deploy was done with frontend and backend separately.
|
||||||
|
* Now we are using only streaming app, so we always want to recreate database (makedata)
|
||||||
|
*/
|
||||||
|
public recreateDatabase: boolean = true
|
||||||
public createDatabaseLoading: boolean = false
|
public createDatabaseLoading: boolean = false
|
||||||
|
public adminGroupsLoading: boolean = false
|
||||||
|
public adminGroups: { id: string; name: string }[] = []
|
||||||
|
|
||||||
/** autoDeployStatus
|
/** autoDeployStatus
|
||||||
* This object presents the status for two steps that we have for deploy.
|
* This object presents the status for two steps that we have for deploy.
|
||||||
@ -50,10 +69,33 @@ export class AutomaticComponent implements OnInit {
|
|||||||
private eventService: EventService,
|
private eventService: EventService,
|
||||||
private deployService: DeployService,
|
private deployService: DeployService,
|
||||||
private sasService: SasService,
|
private sasService: SasService,
|
||||||
|
private sasViyaService: SasViyaService,
|
||||||
private loggerService: LoggerService
|
private loggerService: LoggerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {
|
||||||
|
this.getAdminGroups()
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAdminGroups() {
|
||||||
|
this.adminGroupsLoading = true
|
||||||
|
|
||||||
|
this.sasViyaService.getAdminGroups().subscribe((res: ViyaApiIdentities) => {
|
||||||
|
this.adminGroupsLoading = false
|
||||||
|
// Map admin groups with only needed fields
|
||||||
|
this.adminGroups = res.items.map((item: Item) => {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
(err: any) => {
|
||||||
|
this.adminGroupsLoading = false
|
||||||
|
this.loggerService.error('Error while getting admin groups', err)
|
||||||
|
this.eventService.showAbortModal('admin groups', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes sas.json file to deploy the backend
|
* Executes sas.json file to deploy the backend
|
||||||
@ -63,7 +105,6 @@ export class AutomaticComponent implements OnInit {
|
|||||||
* to create database if checkbox is toggled on
|
* to create database if checkbox is toggled on
|
||||||
*/
|
*/
|
||||||
public async executeJson() {
|
public async executeJson() {
|
||||||
this.autodeploying = true
|
|
||||||
this.isSubmittingJson = true
|
this.isSubmittingJson = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -98,6 +139,14 @@ export class AutomaticComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.isSubmittingJson = false
|
this.isSubmittingJson = false
|
||||||
|
}
|
||||||
|
|
||||||
|
public async runAutoDeploy(executeJson: boolean = false) {
|
||||||
|
this.autodeploying = true
|
||||||
|
|
||||||
|
if (executeJson) {
|
||||||
|
this.executeJson()
|
||||||
|
}
|
||||||
|
|
||||||
if (this.recreateDatabase) {
|
if (this.recreateDatabase) {
|
||||||
this.createDatabase()
|
this.createDatabase()
|
||||||
@ -125,7 +174,7 @@ export class AutomaticComponent implements OnInit {
|
|||||||
* contextName: null is the MUST field for it.
|
* contextName: null is the MUST field for it.
|
||||||
*/
|
*/
|
||||||
let overrideConfig = {
|
let overrideConfig = {
|
||||||
useComputeApi: false,
|
useComputeApi: null,
|
||||||
contextName: this.sasJsConfig.contextName,
|
contextName: this.sasJsConfig.contextName,
|
||||||
debug: true
|
debug: true
|
||||||
}
|
}
|
||||||
@ -148,8 +197,21 @@ export class AutomaticComponent implements OnInit {
|
|||||||
} else {
|
} else {
|
||||||
this.autoDeployStatus.runMakeData = false
|
this.autoDeployStatus.runMakeData = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof res.sasjsAbort !== 'undefined') {
|
||||||
|
const abortRes = res
|
||||||
|
const abortMsg = abortRes.sasjsAbort[0].MSG
|
||||||
|
const macMsg = abortRes.sasjsAbort[0].MAC
|
||||||
|
|
||||||
|
this.eventService.showAbortModal('makedata', abortMsg, {
|
||||||
|
SYSWARNINGTEXT: abortRes.SYSWARNINGTEXT,
|
||||||
|
SYSERRORTEXT: abortRes.SYSERRORTEXT,
|
||||||
|
MAC: macMsg
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: any) => {
|
.catch((err: any) => {
|
||||||
|
this.eventService.showAbortModal('makedata', JSON.stringify(err))
|
||||||
this.autoDeployStatus.runMakeData = false
|
this.autoDeployStatus.runMakeData = false
|
||||||
this.autodeployDone = true
|
this.autodeployDone = true
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
.clear-memory-button {
|
|
||||||
right: 10px;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
@ -1,6 +1,14 @@
|
|||||||
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'
|
import {
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core'
|
||||||
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
||||||
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
||||||
|
import { RequestWrapperResponse } from 'src/app/models/request-wrapper/RequestWrapperResponse'
|
||||||
import { DeployService } from 'src/app/services/deploy.service'
|
import { DeployService } from 'src/app/services/deploy.service'
|
||||||
import { EventService } from 'src/app/services/event.service'
|
import { EventService } from 'src/app/services/event.service'
|
||||||
import { LoggerService } from 'src/app/services/logger.service'
|
import { LoggerService } from 'src/app/services/logger.service'
|
||||||
@ -9,7 +17,8 @@ import { SasService } from 'src/app/services/sas.service'
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-manual-deploy',
|
selector: 'app-manual-deploy',
|
||||||
templateUrl: './manual.component.html',
|
templateUrl: './manual.component.html',
|
||||||
styleUrls: ['./manual.component.scss']
|
styleUrls: ['./manual.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class ManualComponent implements OnInit {
|
export class ManualComponent implements OnInit {
|
||||||
@Input() sasJs!: SASjs
|
@Input() sasJs!: SASjs
|
||||||
@ -265,7 +274,7 @@ export class ManualComponent implements OnInit {
|
|||||||
* contextName: null is the MUST field for it.
|
* contextName: null is the MUST field for it.
|
||||||
*/
|
*/
|
||||||
let overrideConfig = {
|
let overrideConfig = {
|
||||||
useComputeApi: false,
|
useComputeApi: null,
|
||||||
contextName: this.sasJsConfig.contextName,
|
contextName: this.sasJsConfig.contextName,
|
||||||
debug: true
|
debug: true
|
||||||
}
|
}
|
||||||
@ -303,10 +312,10 @@ export class ManualComponent implements OnInit {
|
|||||||
|
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('public/startupservice', null)
|
.request('public/startupservice', null)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.loggerService.log(res)
|
this.loggerService.log(res.adapterResponse)
|
||||||
|
|
||||||
if (res.saslibs) {
|
if (res.adapterResponse.saslibs) {
|
||||||
this.validationState = 'success'
|
this.validationState = 'success'
|
||||||
} else {
|
} else {
|
||||||
this.validationState = 'error'
|
this.validationState = 'error'
|
||||||
|
@ -10,11 +10,13 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="m-0 mt-10">
|
<p class="m-0 mt-10">
|
||||||
Please specify a physical directory below, to which user
|
Please specify a physical directory (on the
|
||||||
<strong>{{ SYSUSERID }}</strong> can write, on behalf of Data Controller:
|
<strong> {{ SYSHOSTNAME }}</strong>
|
||||||
|
compute server) below, to which user
|
||||||
|
<strong>{{ SYSUSERID }}</strong> can write, on behalf of Data Controller.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<label class="mt-20 clr-control-label">DC Directory</label>
|
<label class="mt-20 clr-control-label">DC Staging Directory</label>
|
||||||
<div class="mb-10 clr-control-container">
|
<div class="mb-10 clr-control-container">
|
||||||
<div class="clr-input-wrapper">
|
<div class="clr-input-wrapper">
|
||||||
<input
|
<input
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
.clr-control-container {
|
|
||||||
width: 50vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clr-input-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.thinProgress {
|
|
||||||
left: 0px;
|
|
||||||
right: 0;
|
|
||||||
width: unset;
|
|
||||||
height: 1px;
|
|
||||||
margin-top: 0 !important;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,16 @@
|
|||||||
import { Location } from '@angular/common'
|
import { Location } from '@angular/common'
|
||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
import {
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core'
|
||||||
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
import SASjs, { SASjsConfig } from '@sasjs/adapter'
|
||||||
import { ServerType } from '@sasjs/utils/types/serverType'
|
import { ServerType } from '@sasjs/utils/types/serverType'
|
||||||
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
|
||||||
|
import { RequestWrapperResponse } from 'src/app/models/request-wrapper/RequestWrapperResponse'
|
||||||
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 { SasService } from 'src/app/services/sas.service'
|
import { SasService } from 'src/app/services/sas.service'
|
||||||
@ -11,7 +19,8 @@ import { SasjsService } from 'src/app/services/sasjs.service'
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sasjs-configurator',
|
selector: 'app-sasjs-configurator',
|
||||||
templateUrl: './sasjs-configurator.component.html',
|
templateUrl: './sasjs-configurator.component.html',
|
||||||
styleUrls: ['./sasjs-configurator.component.scss']
|
styleUrls: ['./sasjs-configurator.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class SasjsConfiguratorComponent implements OnInit {
|
export class SasjsConfiguratorComponent implements OnInit {
|
||||||
@Input() sasJs!: SASjs
|
@Input() sasJs!: SASjs
|
||||||
@ -68,11 +77,11 @@ export class SasjsConfiguratorComponent implements OnInit {
|
|||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
this.sasService.request('usernav/usergroupsbymember', null).then(
|
this.sasService.request('usernav/usergroupsbymember', null).then(
|
||||||
(res: any) => {
|
(res: RequestWrapperResponse) => {
|
||||||
this.METAPERSON = res.MF_GETUSER
|
this.METAPERSON = res.adapterResponse.MF_GETUSER
|
||||||
this.SYSUSERID = res.SYSUSERID
|
this.SYSUSERID = res.adapterResponse.SYSUSERID
|
||||||
this.SYSHOSTNAME = res.SYSHOSTNAME
|
this.SYSHOSTNAME = res.adapterResponse.SYSHOSTNAME
|
||||||
this.SYSVLONG = res.SYSVLONG
|
this.SYSVLONG = res.adapterResponse.SYSVLONG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We would like to present a default DCPATH (deployment path) to the
|
We would like to present a default DCPATH (deployment path) to the
|
||||||
@ -88,12 +97,14 @@ export class SasjsConfiguratorComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
this.dcDirectory =
|
this.dcDirectory =
|
||||||
this.tmpDirectories[
|
this.tmpDirectories[
|
||||||
['L', 'H', 'A', 'S'].includes(res.SYSSCPL.substring(0, 1))
|
['L', 'H', 'A', 'S'].includes(
|
||||||
|
res.adapterResponse.SYSSCPL.substring(0, 1)
|
||||||
|
)
|
||||||
? 'linux'
|
? 'linux'
|
||||||
: 'windows'
|
: 'windows'
|
||||||
]
|
]
|
||||||
|
|
||||||
this.dcAdminGroupList = res.groups
|
this.dcAdminGroupList = res.adapterResponse.groups
|
||||||
this.dcAdminGroup = this.dcAdminGroupList[0].GROUPNAME
|
this.dcAdminGroup = this.dcAdminGroupList[0].GROUPNAME
|
||||||
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -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 {}
|
||||||
|
17
client/src/app/directives/steal-focus.directive.ts
Normal file
17
client/src/app/directives/steal-focus.directive.ts
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
.record-edit-modal {
|
|
||||||
.column-entry {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
.name-input-row {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 260px;
|
|
||||||
|
|
||||||
.cell-desc {
|
|
||||||
margin-right: 30px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputs-wrapper {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
::ng-deep >*:not(.date-field):not(clr-select-container) {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::ng-deep {
|
|
||||||
.clr-textarea-wrapper {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clr-form-control {
|
|
||||||
margin-top: 0px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
app-soft-select {
|
|
||||||
display: block;
|
|
||||||
width: 224px;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #999;
|
|
||||||
color: #000;
|
|
||||||
padding: calc(.25rem + 2px) .5rem;
|
|
||||||
border-radius: .125rem;
|
|
||||||
font-size: .541667rem;
|
|
||||||
margin-right: 6px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
background-color: #fff;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background: none;
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-outer-spin-button,
|
|
||||||
&::-webkit-inner-spin-button {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child p:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-field {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 230px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-picker {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 4px;
|
|
||||||
|
|
||||||
::ng-deep {
|
|
||||||
// clr-datepicker-view-manager {
|
|
||||||
// transform: unset !important;
|
|
||||||
// left: unset !important;
|
|
||||||
// right: 70px !important;
|
|
||||||
// }
|
|
||||||
.clr-input-group {
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::ng-deep {
|
|
||||||
clr-select-container {
|
|
||||||
border: 1px solid #999;
|
|
||||||
color: #000;
|
|
||||||
border-radius: .125rem;
|
|
||||||
margin-right: 5px;
|
|
||||||
|
|
||||||
.clr-select-wrapper {
|
|
||||||
max-height: unset;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
top: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
height: auto;
|
|
||||||
padding: 10px;
|
|
||||||
padding-right: 20px;
|
|
||||||
border: 0 !important;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background: 0 0 !important;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clr-input-container {
|
|
||||||
width: 224px;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #999;
|
|
||||||
color: #000;
|
|
||||||
padding: calc(.25rem + 2px) .5rem;
|
|
||||||
border-radius: .125rem;
|
|
||||||
font-size: .541667rem;
|
|
||||||
margin-right: 6px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background: none;
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-outer-spin-button,
|
|
||||||
&::-webkit-inner-spin-button {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.invalid-data {
|
|
||||||
border-color: red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clr-control-container {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
resize: none;
|
|
||||||
border-color: #999;
|
|
||||||
|
|
||||||
&.invalid-data {
|
|
||||||
border-color: red;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.not-char {
|
|
||||||
font-family: "Lucida Console", Monaco, monospace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.generate-record-url {
|
|
||||||
right: 40px;
|
|
||||||
top: 40px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generate-record-url-button {
|
|
||||||
right: 25px;
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header {
|
|
||||||
padding: 0 0 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
// height: 65px;
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.prev-next {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin: 0px 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.focusable {
|
|
||||||
&:focus {
|
|
||||||
box-shadow: 0 0 3px 0px #5aa220;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-input-left-offset {
|
|
||||||
left: -30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.validation-info-alert {
|
|
||||||
width: 310px
|
|
||||||
}
|
|
@ -1,5 +1,12 @@
|
|||||||
import { KeyValue } from '@angular/common'
|
import { KeyValue } from '@angular/common'
|
||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
import {
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { ValidateFilterSASResponse } from 'src/app/models/sas/validate-filter.model'
|
import { ValidateFilterSASResponse } from 'src/app/models/sas/validate-filter.model'
|
||||||
import { QueryClause } from 'src/app/models/TableData'
|
import { QueryClause } from 'src/app/models/TableData'
|
||||||
@ -16,7 +23,8 @@ import { EditRecordModal } from '../../models/EditRecordModal'
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-record',
|
selector: 'app-edit-record',
|
||||||
templateUrl: './edit-record.component.html',
|
templateUrl: './edit-record.component.html',
|
||||||
styleUrls: ['./edit-record.component.scss']
|
styleUrls: ['./edit-record.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class EditRecordComponent implements OnInit {
|
export class EditRecordComponent implements OnInit {
|
||||||
@Input() currentRecord!: EditRecordModal
|
@Input() currentRecord!: EditRecordModal
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
:host {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Goal of this component is to recieve array of strings where every element is one state
|
* Goal of this component is to recieve array of strings where every element is one state
|
||||||
@ -10,7 +10,8 @@ import { Component, OnInit } from '@angular/core'
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-upload-stater',
|
selector: 'app-upload-stater',
|
||||||
templateUrl: './upload-stater.component.html',
|
templateUrl: './upload-stater.component.html',
|
||||||
styleUrls: ['./upload-stater.component.scss']
|
styleUrls: ['./upload-stater.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class UploadStaterComponent implements OnInit {
|
export class UploadStaterComponent implements OnInit {
|
||||||
public statesList: string[] = [] //States appended to be displayed
|
public statesList: string[] = [] //States appended to be displayed
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
appFileDrop
|
appFileDrop
|
||||||
(fileOver)="fileOverBase($event)"
|
(fileOver)="fileOverBase($event)"
|
||||||
[uploader]="uploader"
|
[uploader]="uploader"
|
||||||
(fileDrop)="getFileDesc($event, true)"
|
(fileDrop)="attachFile($event, true)"
|
||||||
[clrModalSize]="'xl'"
|
[clrModalSize]="'xl'"
|
||||||
[clrModalStaticBackdrop]="false"
|
[clrModalStaticBackdrop]="false"
|
||||||
[clrModalClosable]="excelUploadState === 'Validating-DQ'"
|
[clrModalClosable]="excelUploadState === 'Validating-DQ'"
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<div class="clr-row card-block mt-15 d-flex justify-content-between">
|
<div class="clr-row card-block mt-15 d-flex justify-content-between">
|
||||||
<div class="clr-col-md-auto">
|
<div class="clr-col-md-auto">
|
||||||
<div class="encoding-block">
|
<div class="encoding-block">
|
||||||
<clr-radio-container class="mt-0-i" clrInline>
|
<clr-radio-container class="mt-0" clrInline>
|
||||||
<clr-radio-wrapper>
|
<clr-radio-wrapper>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@ -81,7 +81,7 @@
|
|||||||
type="file"
|
type="file"
|
||||||
appFileSelect
|
appFileSelect
|
||||||
[uploader]="uploader"
|
[uploader]="uploader"
|
||||||
(change)="getFileDesc($event)"
|
(change)="attachFile($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -92,7 +92,7 @@
|
|||||||
<button
|
<button
|
||||||
[disabled]="true"
|
[disabled]="true"
|
||||||
class="btnView btn btn-sm btn-success profile-buttons w-100"
|
class="btnView btn btn-sm btn-success profile-buttons w-100"
|
||||||
(click)="getFile()"
|
(click)="uploadParsedFiles()"
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
</button>
|
</button>
|
||||||
@ -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
|
||||||
@ -184,11 +193,14 @@
|
|||||||
libName: (libds?.split('.'))![0],
|
libName: (libds?.split('.'))![0],
|
||||||
tableName: (libds?.split('.'))![1]
|
tableName: (libds?.split('.'))![1]
|
||||||
} as libdsParsed"
|
} as libdsParsed"
|
||||||
class="editor-title text-center mt-0-i"
|
class="editor-title text-center mt-0"
|
||||||
>
|
>
|
||||||
|
<clr-tooltip>
|
||||||
<clr-icon
|
<clr-icon
|
||||||
|
clrTooltipTrigger
|
||||||
(click)="datasetInfo = true"
|
(click)="datasetInfo = true"
|
||||||
shape="info-circle"
|
shape="info-circle"
|
||||||
|
aria-label="View dataset meta info"
|
||||||
class="is-highlight cursor-pointer"
|
class="is-highlight cursor-pointer"
|
||||||
size="24"
|
size="24"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
@ -199,11 +211,25 @@
|
|||||||
class="color-yellow"
|
class="color-yellow"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
|
|
||||||
|
<span clrTooltipTrigger>
|
||||||
{{ libdsParsed.libName }}.<a
|
{{ libdsParsed.libName }}.<a
|
||||||
class="mr-10"
|
class="mr-10 view-table"
|
||||||
[routerLink]="'/view/data/' + libds!"
|
[routerLink]="'/view/data/' + libds!"
|
||||||
>{{ libdsParsed.tableName.replace('-FC', '') }}</a
|
>{{ 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>
|
||||||
|
|
||||||
<ng-container *ngIf="dataSource">
|
<ng-container *ngIf="dataSource">
|
||||||
<ng-container *ngIf="!zeroFilterRows">
|
<ng-container *ngIf="!zeroFilterRows">
|
||||||
({{ dataSource.length | thousandSeparator: ',' }}
|
({{ dataSource.length | thousandSeparator: ',' }}
|
||||||
@ -215,34 +241,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 +309,7 @@
|
|||||||
licenceState.value.editor_rows_allowed === 1
|
licenceState.value.editor_rows_allowed === 1
|
||||||
? 'row'
|
? 'row'
|
||||||
: 'rows'
|
: 'rows'
|
||||||
}}, contact support@datacontroller.io</span
|
}}, contact support@datacontroller.io</span
|
||||||
>
|
>
|
||||||
</clr-tooltip-content>
|
</clr-tooltip-content>
|
||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
@ -346,8 +375,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 +385,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 +411,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 +447,7 @@
|
|||||||
licenceState.value.editor_rows_allowed === 1
|
licenceState.value.editor_rows_allowed === 1
|
||||||
? 'row'
|
? 'row'
|
||||||
: 'rows'
|
: 'rows'
|
||||||
}}, contact support@datacontroller.io</span
|
}}, contact support@datacontroller.io</span
|
||||||
>
|
>
|
||||||
</clr-tooltip-content>
|
</clr-tooltip-content>
|
||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
@ -467,14 +497,18 @@
|
|||||||
: 'rows'
|
: 'rows'
|
||||||
}}
|
}}
|
||||||
will be submitted. To remove the restriction, contact
|
will be submitted. To remove the restriction, contact
|
||||||
support@datacontroller.io</span
|
support@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 +516,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 +537,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 +546,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 +563,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@datacontroller.io
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
@ -542,7 +577,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm btn-primary"
|
class="btn btn-sm btn-primary"
|
||||||
(click)="getFile(); submitLimitNotice = false"
|
(click)="uploadParsedFiles(); submitLimitNotice = false"
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
@ -830,6 +865,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>
|
||||||
|
@ -1,223 +0,0 @@
|
|||||||
.card {
|
|
||||||
margin-top: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttonBar {
|
|
||||||
padding: 2px 10px 2px 10px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.testRed {
|
|
||||||
color: white;
|
|
||||||
background: rgba(255,0,0, 0.8) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
hot-table {
|
|
||||||
::ng-deep {
|
|
||||||
.firstColumnHeaderStyle button.changeType {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handsontable tbody th.ht__highlight, .handsontable thead th.ht__highlight {
|
|
||||||
&.primaryKeyHeaderStyle {
|
|
||||||
background: #306b00b0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.primaryKeyHeaderStyle {
|
|
||||||
background: #306b006e;
|
|
||||||
}
|
|
||||||
|
|
||||||
th.readonlyCell {
|
|
||||||
div {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
td.readonlyCell {
|
|
||||||
opacity: 0.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.infoBar {
|
|
||||||
margin-top:14px;
|
|
||||||
background: #495967;
|
|
||||||
color: white;
|
|
||||||
text-align:center;
|
|
||||||
padding: 3px;
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
height: 30px;
|
|
||||||
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
span {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
height: unset;
|
|
||||||
white-space: normal;
|
|
||||||
|
|
||||||
span {
|
|
||||||
width: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pkHeader {
|
|
||||||
background: #687682;
|
|
||||||
color: #fff;
|
|
||||||
margin: -1px -1px -1px -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerBar {
|
|
||||||
// padding: 13px 0px 14px 0px;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
background: #ffffff;
|
|
||||||
background: #f5f6fe;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-icon {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btnCtrl {
|
|
||||||
display:flex;
|
|
||||||
justify-content:flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
border-bottom: 1px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-drop-zone {
|
|
||||||
border: solid 1px lightgray;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: whitesmoke;
|
|
||||||
box-shadow: inset 0px 0px 4px 2px #a7a5a52b;
|
|
||||||
height: 50vh;
|
|
||||||
}
|
|
||||||
.nv-file-over {
|
|
||||||
border: solid 2px green;
|
|
||||||
} /* Default class applied to drop zones on over */
|
|
||||||
|
|
||||||
.file-drop-text{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nv-file-over {
|
|
||||||
border: solid 2px green;
|
|
||||||
} /* Default class applied to drop zones on over */
|
|
||||||
|
|
||||||
.file-drop-text{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
|
|
||||||
.progresStatic {
|
|
||||||
margin-top:9px!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress, .progress-static {
|
|
||||||
width: calc(100% - 14px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hotEditor {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.excel-parsing {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.details {
|
|
||||||
margin: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: -45px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-record-spinner {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
background: rgba(255, 255, 255, 0.6);
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 480px) {
|
|
||||||
|
|
||||||
.progresStatic {
|
|
||||||
margin-top:32px!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-block, .card-footer {
|
|
||||||
padding: 10px 0px 0px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-area {
|
|
||||||
padding: 0 0.8rem 0.8rem 0.8rem !important;
|
|
||||||
padding-top: 0;
|
|
||||||
|
|
||||||
// .card {
|
|
||||||
// min-height: calc(100vh - 160px);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
.drop-area {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
margin: 1px;
|
|
||||||
|
|
||||||
border: 2px dashed #fff;
|
|
||||||
|
|
||||||
z-index: -1;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 20px;
|
|
||||||
margin-top: 20px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#submitBtn, #cancelSubmitBtn {
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME
|
|
||||||
// Let's leave it here for a reference if there
|
|
||||||
// is an issue with viewboxes/filter modal overlaying
|
|
||||||
// we will remove it if no issues found
|
|
||||||
// .filter-modal {
|
|
||||||
// z-index: 1210;
|
|
||||||
// }
|
|
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||||
|
@ -11,9 +11,11 @@ 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
|
||||||
}
|
}
|
||||||
@ -31,6 +33,8 @@ 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
|
||||||
@ -50,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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
.sidebar-height{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.group-info-text{
|
|
||||||
display: inline;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
.group-info{
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border: 1px solid #a7a7a7;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: 0px 2px 5px #dad7d7;
|
|
||||||
}
|
|
||||||
.group-info td{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-data{
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border: 1px solid #a7a7a7;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: 0px 2px 5px #dad7d7;
|
|
||||||
}
|
|
||||||
.group-data{
|
|
||||||
min-height: auto;
|
|
||||||
h3, h5{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.member-table{
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.member-table thead{
|
|
||||||
background-color: #dadada;
|
|
||||||
}
|
|
||||||
.member-table tbody{
|
|
||||||
tr:hover{
|
|
||||||
background-color: #e6e6e6;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.table-container{
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 768px){
|
|
||||||
.group-data{
|
|
||||||
min-height: unset !important;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,12 @@
|
|||||||
import { Location } from '@angular/common'
|
import { Location } from '@angular/common'
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { SASjsConfig } from '@sasjs/adapter'
|
import { SASjsConfig } from '@sasjs/adapter'
|
||||||
import { ServerType } from '@sasjs/utils/types/serverType'
|
import { ServerType } from '@sasjs/utils/types/serverType'
|
||||||
import { HelperService } from '../services/helper.service'
|
import { HelperService } from '../services/helper.service'
|
||||||
import { SasService } from '../services/sas.service'
|
import { SasService } from '../services/sas.service'
|
||||||
import { globals } from '../_globals'
|
import { globals } from '../_globals'
|
||||||
|
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-group',
|
selector: 'app-group',
|
||||||
@ -13,7 +14,8 @@ import { globals } from '../_globals'
|
|||||||
styleUrls: ['./group.component.scss'],
|
styleUrls: ['./group.component.scss'],
|
||||||
host: {
|
host: {
|
||||||
class: 'content-container'
|
class: 'content-container'
|
||||||
}
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class GroupComponent implements OnInit {
|
export class GroupComponent implements OnInit {
|
||||||
public groups: Array<any> | undefined
|
public groups: Array<any> | undefined
|
||||||
@ -82,10 +84,12 @@ export class GroupComponent implements OnInit {
|
|||||||
globals.usernav.groupList = groups
|
globals.usernav.groupList = groups
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.sasService.request('public/getgroups', null).then((res: any) => {
|
this.sasService
|
||||||
|
.request('public/getgroups', null)
|
||||||
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.groups = res.groups
|
this.groups = res.adapterResponse.groups
|
||||||
globals.usernav.groupList = res.groups
|
globals.usernav.groupList = res.adapterResponse.groups
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -128,14 +132,15 @@ export class GroupComponent implements OnInit {
|
|||||||
let data = { iwant: [{ groupid: this.paramURI }] }
|
let data = { iwant: [{ groupid: this.paramURI }] }
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('usernav/usermembersbygroup', data)
|
.request('usernav/usermembersbygroup', data)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.groupMembers = res.sasmembers
|
this.groupMembers = res.adapterResponse.sasmembers
|
||||||
this.groupMemberCount = res.sasmembers.length
|
this.groupMemberCount = res.adapterResponse.sasmembers.length
|
||||||
if (res.sasmembers[0] !== undefined) {
|
if (res.adapterResponse.sasmembers[0] !== undefined) {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.groupUri = res.sasmembers[0].URIMEM || this.paramURI
|
this.groupUri =
|
||||||
this.groupName = res.sasmembers[0].GROUPNAME
|
res.adapterResponse.sasmembers[0].URIMEM || this.paramURI
|
||||||
this.groupDesc = res.sasmembers[0].GROUPDESC
|
this.groupName = res.adapterResponse.sasmembers[0].GROUPNAME
|
||||||
|
this.groupDesc = res.adapterResponse.sasmembers[0].GROUPDESC
|
||||||
|
|
||||||
if (!this.groupName) {
|
if (!this.groupName) {
|
||||||
this.groupName = this.paramURI
|
this.groupName = this.paramURI
|
||||||
@ -202,13 +207,13 @@ export class GroupComponent implements OnInit {
|
|||||||
|
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('usernav/usermembersbygroup', data)
|
.request('usernav/usermembersbygroup', data)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.groupUri = group.GROUPURI
|
this.groupUri = group.GROUPURI
|
||||||
this.groupName = group.GROUPNAME
|
this.groupName = group.GROUPNAME
|
||||||
this.groupDesc = group.GROUPDESC
|
this.groupDesc = group.GROUPDESC
|
||||||
this.groupMembers = res.sasmembers
|
this.groupMembers = res.adapterResponse.sasmembers
|
||||||
this.groupMemberCount = res.sasmembers.length
|
this.groupMemberCount = res.adapterResponse.sasmembers.length
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
client/src/app/home/home-routing.module.ts
Normal file
25
client/src/app/home/home-routing.module.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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'
|
||||||
|
import { MultiDatasetModule } from '../multi-dataset/multi-dataset.module'
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: HomeRouteComponent,
|
||||||
|
children: [
|
||||||
|
{ path: '', pathMatch: 'full', redirectTo: 'tables' },
|
||||||
|
{ path: 'tables', component: HomeComponent },
|
||||||
|
{ path: 'excel-maps', loadChildren: () => XLMapModule },
|
||||||
|
{ path: 'multi-load', loadChildren: () => MultiDatasetModule }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class HomeRoutingModule {}
|
@ -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>
|
||||||
|
|
||||||
|
<ng-container *ngIf="tableLocked">
|
||||||
<clr-tooltip-content
|
<clr-tooltip-content
|
||||||
clrPosition="bottom-right"
|
clrPosition="bottom-right"
|
||||||
clrSize="lg"
|
clrSize="lg"
|
||||||
*clrIfOpen
|
*clrIfOpen
|
||||||
>
|
>
|
||||||
<span *ngIf="tableLocked">
|
<span>
|
||||||
To unlock all tables, contact support@datacontroller.io
|
To unlock all tables, contact support@datacontroller.io
|
||||||
</span>
|
</span>
|
||||||
</clr-tooltip-content>
|
</clr-tooltip-content>
|
||||||
|
</ng-container>
|
||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
</clr-tree-node>
|
</clr-tree-node>
|
||||||
</clr-tree-node>
|
</clr-tree-node>
|
||||||
@ -119,17 +123,25 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!loading" class="no-table-selected">
|
<div *ngIf="!loading" class="no-table-selected">
|
||||||
<clr-icon
|
<img
|
||||||
shape="warning-standard"
|
src="images/select-table.png"
|
||||||
size="60"
|
class="select-table-icon"
|
||||||
class="is-info icon-dc-fill"
|
alt="select table 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>
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
clr-tree-node button {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-block {
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-table-selected {
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
::ng-deep {
|
|
||||||
// .badge.badge-info {
|
|
||||||
// background: #6a9235!important;
|
|
||||||
// color: #fff;
|
|
||||||
// }
|
|
||||||
clr-icon.is-blue, clr-icon.is-info {
|
|
||||||
fill: #6a9235;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner-wrapper-fullpage {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
@ -3,7 +3,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { Component, AfterContentInit } from '@angular/core'
|
import { Component, AfterContentInit, ViewEncapsulation } from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
import { globals } from '../_globals'
|
import { globals } from '../_globals'
|
||||||
@ -18,7 +18,8 @@ import { LicenceService } from '../services/licence.service'
|
|||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
host: {
|
host: {
|
||||||
class: 'content-container'
|
class: 'content-container'
|
||||||
}
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class HomeComponent implements AfterContentInit {
|
export class HomeComponent implements AfterContentInit {
|
||||||
public treeNodeLibraries: Array<any> | null = null
|
public treeNodeLibraries: Array<any> | null = null
|
||||||
|
@ -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,
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
<div class="card-header">Licencing</div>
|
<div class="card-header">Licencing</div>
|
||||||
|
|
||||||
<div [ngSwitch]="action" class="card-block">
|
<div [ngSwitch]="action" class="card-block">
|
||||||
|
<div class="card-text">
|
||||||
<ng-container *ngSwitchCase="'key'">
|
<ng-container *ngSwitchCase="'key'">
|
||||||
<p class="key-error" *ngIf="!keyError">
|
<p class="key-error" *ngIf="!keyError">
|
||||||
Licence key is invalid. We can't provide you more details at the moment
|
Licence key is invalid. We can't provide you more details at the
|
||||||
|
moment
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
@ -126,7 +128,9 @@
|
|||||||
</clr-tab-content>
|
</clr-tab-content>
|
||||||
</clr-tab>
|
</clr-tab>
|
||||||
</clr-tabs>
|
</clr-tabs>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-footer d-flex clr-align-items-center">
|
||||||
<button
|
<button
|
||||||
(click)="applyKeys()"
|
(click)="applyKeys()"
|
||||||
class="btn btn-primary apply-keys"
|
class="btn btn-primary apply-keys"
|
||||||
@ -145,5 +149,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<app-terms *ngIf="action === 'register'"></app-terms>
|
<app-terms *ngIf="action === 'register'"></app-terms>
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
:host {
|
|
||||||
height: calc(100% - 96px);
|
|
||||||
padding: 20px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-error {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.misskey {
|
|
||||||
color: #E74C3C;
|
|
||||||
}
|
|
||||||
|
|
||||||
.license-key-form, .activation-key-form {
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
.clr-control-container {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
height: 170px;
|
|
||||||
max-height: 170px;
|
|
||||||
min-height: 170px;
|
|
||||||
resize: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.apply-keys {
|
|
||||||
height: 40px;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drop-area {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 15px;
|
|
||||||
border: 2px dashed #b2b2b2;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clr-tabs button {
|
|
||||||
box-shadow: none !important
|
|
||||||
}
|
|
@ -1,7 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { AppService, LicenceService, SasService } from '../services'
|
import { AppService, LicenceService, SasService } from '../services'
|
||||||
import { LicenseKeyData } from '../models/LicenseKeyData'
|
import { LicenseKeyData } from '../models/LicenseKeyData'
|
||||||
|
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
|
||||||
|
|
||||||
enum LicenseActions {
|
enum LicenseActions {
|
||||||
key = 'key',
|
key = 'key',
|
||||||
@ -13,7 +14,8 @@ enum LicenseActions {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-licensing',
|
selector: 'app-licensing',
|
||||||
templateUrl: './licensing.component.html',
|
templateUrl: './licensing.component.html',
|
||||||
styleUrls: ['./licensing.component.scss']
|
styleUrls: ['./licensing.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class LicensingComponent implements OnInit {
|
export class LicensingComponent implements OnInit {
|
||||||
public action: LicenseActions | null = null
|
public action: LicenseActions | null = null
|
||||||
@ -116,8 +118,12 @@ export class LicensingComponent implements OnInit {
|
|||||||
|
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('admin/registerkey', table)
|
.request('admin/registerkey', table)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
if (res.return && res.return[0] && res.return[0].MSG === 'SUCCESS') {
|
if (
|
||||||
|
res.adapterResponse.return &&
|
||||||
|
res.adapterResponse.return[0] &&
|
||||||
|
res.adapterResponse.return[0].MSG === 'SUCCESS'
|
||||||
|
) {
|
||||||
location.replace(location.href.split('#')[0])
|
location.replace(location.href.split('#')[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -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)="
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
.toggle-switch input[type=checkbox]:checked+label:before {
|
|
||||||
border-color: #314351;
|
|
||||||
background-color: #314351!important;
|
|
||||||
transition: .15s ease-in;
|
|
||||||
transition-property: border-color,background-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
#graph{
|
|
||||||
height: calc(100vh - 195px);
|
|
||||||
overflow: hidden;
|
|
||||||
text-align: center;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #e4e4e4;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selection-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 670px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-active {
|
|
||||||
background: #d8e3e9;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-area {
|
|
||||||
padding: 0.5rem !important;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
min-height: calc(100vh - 120px);
|
|
||||||
|
|
||||||
.card-block {
|
|
||||||
padding: 0.5rem 0.35rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clr-tree-node button {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.graph-render-spinner {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.biglineage-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-footer {
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.lineage-title-wrapper {
|
|
||||||
left: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-depth-input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.toggle-switch-container {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component, ViewEncapsulation } from '@angular/core'
|
||||||
import { Location } from '@angular/common'
|
import { Location } from '@angular/common'
|
||||||
import { globals } from '../_globals'
|
import { globals } from '../_globals'
|
||||||
import * as d3Viz from 'd3-graphviz'
|
import * as d3Viz from 'd3-graphviz'
|
||||||
@ -9,6 +9,7 @@ import { SasService } from '../services/sas.service'
|
|||||||
import * as saveSvg from 'save-svg-as-png'
|
import * as saveSvg from 'save-svg-as-png'
|
||||||
import { LoggerService } from '../services/logger.service'
|
import { LoggerService } from '../services/logger.service'
|
||||||
import { LicenceService } from '../services/licence.service'
|
import { LicenceService } from '../services/licence.service'
|
||||||
|
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -17,7 +18,8 @@ const moment = require('moment')
|
|||||||
templateUrl: './lineage.component.html',
|
templateUrl: './lineage.component.html',
|
||||||
host: {
|
host: {
|
||||||
class: 'content-container'
|
class: 'content-container'
|
||||||
}
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class LineageComponent {
|
export class LineageComponent {
|
||||||
public switchFlag: boolean = false
|
public switchFlag: boolean = false
|
||||||
@ -115,8 +117,8 @@ export class LineageComponent {
|
|||||||
|
|
||||||
await this.sasService
|
await this.sasService
|
||||||
.request('lineage/getmetacols', libTable)
|
.request('lineage/getmetacols', libTable)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.columnsList = res.metacols
|
this.columnsList = res.adapterResponse.metacols
|
||||||
if (this.columnsList && this.columnsList.length > 0) {
|
if (this.columnsList && this.columnsList.length > 0) {
|
||||||
// this.column = this.columnsList[0]['COLURI']
|
// this.column = this.columnsList[0]['COLURI']
|
||||||
|
|
||||||
@ -174,8 +176,8 @@ export class LineageComponent {
|
|||||||
let libTable = { SASControlTable: [{ liburi: $event }] }
|
let libTable = { SASControlTable: [{ liburi: $event }] }
|
||||||
await this.sasService
|
await this.sasService
|
||||||
.request('lineage/getmetatables', libTable)
|
.request('lineage/getmetatables', libTable)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.tablesList = res.metatables
|
this.tablesList = res.adapterResponse.metatables
|
||||||
|
|
||||||
if (this.tablesList && this.tablesList.length > 0) {
|
if (this.tablesList && this.tablesList.length > 0) {
|
||||||
library['tables'] = this.tablesList
|
library['tables'] = this.tablesList
|
||||||
@ -295,8 +297,8 @@ export class LineageComponent {
|
|||||||
} else {
|
} else {
|
||||||
await this.sasService
|
await this.sasService
|
||||||
.request('public/viewlibs', null)
|
.request('public/viewlibs', null)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.libraryList = res.saslibs
|
this.libraryList = res.adapterResponse.saslibs
|
||||||
this.helperService.displayLibraries(this.libraryList)
|
this.helperService.displayLibraries(this.libraryList)
|
||||||
|
|
||||||
if (this.libraryList) {
|
if (this.libraryList) {
|
||||||
@ -402,8 +404,8 @@ export class LineageComponent {
|
|||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('lineage/fetchtablelineage', libTable)
|
.request('lineage/fetchtablelineage', libTable)
|
||||||
.then(async (res: any) => {
|
.then(async (res: RequestWrapperResponse) => {
|
||||||
if (res.flatdata.length > 0) {
|
if (res.adapterResponse.flatdata.length > 0) {
|
||||||
if (this.licenceService.checkLineageLimit()) {
|
if (this.licenceService.checkLineageLimit()) {
|
||||||
this.eventService.showInfoModal(
|
this.eventService.showInfoModal(
|
||||||
'Notice',
|
'Notice',
|
||||||
@ -421,20 +423,22 @@ export class LineageComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.lineageTableName =
|
this.lineageTableName =
|
||||||
res.info[0].LIBREF + '.' + res.info[0].TABLENAME
|
res.adapterResponse.info[0].LIBREF +
|
||||||
|
'.' +
|
||||||
|
res.adapterResponse.info[0].TABLENAME
|
||||||
|
|
||||||
let dotArray = res.finalfinal
|
let dotArray = res.adapterResponse.finalfinal
|
||||||
let vizTmp: string = ''
|
let vizTmp: string = ''
|
||||||
|
|
||||||
for (let i = 0; i < dotArray.length; i++) {
|
for (let i = 0; i < dotArray.length; i++) {
|
||||||
vizTmp += unescape(dotArray[i].LINE) + '\n'
|
vizTmp += unescape(dotArray[i].LINE) + '\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
this.flatdata = res.flatdata
|
this.flatdata = res.adapterResponse.flatdata
|
||||||
|
|
||||||
if (this.libraryList) {
|
if (this.libraryList) {
|
||||||
let libraryToSelect = this.libraryList.find((library: any) =>
|
let libraryToSelect = this.libraryList.find((library: any) =>
|
||||||
res.info[0].LIBURI.toUpperCase().includes(
|
res.adapterResponse.info[0].LIBURI.toUpperCase().includes(
|
||||||
library.LIBRARYID.toUpperCase()
|
library.LIBRARYID.toUpperCase()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -450,7 +454,7 @@ export class LineageComponent {
|
|||||||
if (libraryToSelect['tables']) {
|
if (libraryToSelect['tables']) {
|
||||||
tableToSelect = libraryToSelect['tables'].find((table: any) =>
|
tableToSelect = libraryToSelect['tables'].find((table: any) =>
|
||||||
table.TABLEURI.toUpperCase().includes(
|
table.TABLEURI.toUpperCase().includes(
|
||||||
res.info[0].TABLEID.toUpperCase()
|
res.adapterResponse.info[0].TABLEID.toUpperCase()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -495,10 +499,10 @@ export class LineageComponent {
|
|||||||
.replace(/\sds:/g, '\nds:')
|
.replace(/\sds:/g, '\nds:')
|
||||||
.replace(/\s\n/g, '\n')
|
.replace(/\s\n/g, '\n')
|
||||||
|
|
||||||
this.idlookup = res.idlookup
|
this.idlookup = res.adapterResponse.idlookup
|
||||||
|
|
||||||
if (res.finalfinal.length > this.largeDotFileLimit) {
|
if (res.adapterResponse.finalfinal.length > this.largeDotFileLimit) {
|
||||||
this.largeDotFileLines = res.finalfinal.length
|
this.largeDotFileLines = res.adapterResponse.finalfinal.length
|
||||||
} else {
|
} else {
|
||||||
this.buildGraph()
|
this.buildGraph()
|
||||||
}
|
}
|
||||||
@ -619,8 +623,8 @@ export class LineageComponent {
|
|||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.sasService
|
this.sasService
|
||||||
.request('lineage/fetchcollineage', libTable)
|
.request('lineage/fetchcollineage', libTable)
|
||||||
.then(async (res: any) => {
|
.then(async (res: RequestWrapperResponse) => {
|
||||||
if (res.flatdata.length > 0) {
|
if (res.adapterResponse.flatdata.length > 0) {
|
||||||
if (this.licenceService.checkLineageLimit()) {
|
if (this.licenceService.checkLineageLimit()) {
|
||||||
this.eventService.showInfoModal(
|
this.eventService.showInfoModal(
|
||||||
'Notice',
|
'Notice',
|
||||||
@ -631,18 +635,21 @@ export class LineageComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof res === 'string') {
|
if (typeof res.adapterResponse === 'string') {
|
||||||
this.vizInput = 'digraph G {SAS Error}'
|
this.vizInput = 'digraph G {SAS Error}'
|
||||||
this.buildGraph()
|
this.buildGraph()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lineageTableName = res.info[0].LIBREF + '.' + res.info[0].TABNAME
|
this.lineageTableName =
|
||||||
this.lineageColumnName = res.info[0].COLNAME
|
res.adapterResponse.info[0].LIBREF +
|
||||||
|
'.' +
|
||||||
|
res.adapterResponse.info[0].TABNAME
|
||||||
|
this.lineageColumnName = res.adapterResponse.info[0].COLNAME
|
||||||
|
|
||||||
this.idlookup = res.idlookup
|
this.idlookup = res.adapterResponse.idlookup
|
||||||
|
|
||||||
let dotArray = res.fromsas
|
let dotArray = res.adapterResponse.fromsas
|
||||||
let vizTmp: string = ''
|
let vizTmp: string = ''
|
||||||
for (let i = 0; i < dotArray.length; i++) {
|
for (let i = 0; i < dotArray.length; i++) {
|
||||||
vizTmp += unescape(dotArray[i].STRING) + '\n'
|
vizTmp += unescape(dotArray[i].STRING) + '\n'
|
||||||
@ -653,12 +660,11 @@ export class LineageComponent {
|
|||||||
.replace(/\sds:/g, '\nds:')
|
.replace(/\sds:/g, '\nds:')
|
||||||
.replace(/\s\n/g, '\n')
|
.replace(/\s\n/g, '\n')
|
||||||
|
|
||||||
this.flatdata = res.flatdata
|
this.flatdata = res.adapterResponse.flatdata
|
||||||
|
|
||||||
if (this.libraryList) {
|
if (this.libraryList) {
|
||||||
let libraryToSelect = this.libraryList.find(
|
let libraryToSelect = this.libraryList.find((library: any) =>
|
||||||
(library: any) =>
|
res.adapterResponse.info[0]?.LIBURI?.toUpperCase()?.includes(
|
||||||
res.info[0]?.LIBURI?.toUpperCase()?.includes(
|
|
||||||
library?.LIBRARYID?.toUpperCase()
|
library?.LIBRARYID?.toUpperCase()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -673,7 +679,8 @@ export class LineageComponent {
|
|||||||
|
|
||||||
if (libraryToSelect['tables']) {
|
if (libraryToSelect['tables']) {
|
||||||
tableToSelect = libraryToSelect['tables'].find(
|
tableToSelect = libraryToSelect['tables'].find(
|
||||||
(table: any) => table.TABLEURI === res.info[0].TABURI
|
(table: any) =>
|
||||||
|
table.TABLEURI === res.adapterResponse.info[0].TABURI
|
||||||
)
|
)
|
||||||
|
|
||||||
if (tableToSelect) {
|
if (tableToSelect) {
|
||||||
@ -715,8 +722,8 @@ export class LineageComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.fromsas.length > this.largeDotFileLimit) {
|
if (res.adapterResponse.fromsas.length > this.largeDotFileLimit) {
|
||||||
this.largeDotFileLines = res.fromsas.length
|
this.largeDotFileLines = res.adapterResponse.fromsas.length
|
||||||
} else {
|
} else {
|
||||||
this.buildGraph()
|
this.buildGraph()
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
>
|
>
|
||||||
|
<div>
|
||||||
<clr-icon
|
<clr-icon
|
||||||
*ngIf="!entry.count"
|
*ngIf="!entry.count"
|
||||||
shape="rack-server"
|
shape="rack-server"
|
||||||
></clr-icon>
|
></clr-icon>
|
||||||
<clr-icon *ngIf="entry.count" shape="block"></clr-icon>
|
<clr-icon
|
||||||
|
*ngIf="entry.count"
|
||||||
|
shape="block"
|
||||||
|
></clr-icon>
|
||||||
{{ entry.display }}
|
{{ 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="rack-server"
|
||||||
|
></clr-icon>
|
||||||
<clr-icon *ngIf="entry.count" shape="block"></clr-icon>
|
<clr-icon *ngIf="entry.count" shape="block"></clr-icon>
|
||||||
{{ entry.display }}
|
{{ 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>
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
|
|
||||||
.objects-col{
|
|
||||||
height: 75vh;
|
|
||||||
overflow: scroll;
|
|
||||||
border: 1px solid #cccccc;
|
|
||||||
background: white;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cols-head {
|
|
||||||
background: #fafafa;
|
|
||||||
border: 1px solid #cccccc;
|
|
||||||
padding: 10px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.object-text {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-left: 10px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.repo-dropdown{
|
|
||||||
margin-right: 15px;
|
|
||||||
margin-left: 15px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.clr-accordion-title{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.float-right{
|
|
||||||
margin: 0px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.full-width{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.object-uri{
|
|
||||||
margin: 0px;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
.object-header{
|
|
||||||
padding-left: 3px;
|
|
||||||
padding-right: 3px;
|
|
||||||
}
|
|
||||||
.object-header:hover{
|
|
||||||
background-color: #d8e3e9;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
.datagrid-host{
|
|
||||||
display: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
margin-top: 0;
|
|
||||||
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-area {
|
|
||||||
padding: 0.5rem !important;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
import { Location } from '@angular/common'
|
import { Location } from '@angular/common'
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { ClrDatagridStringFilterInterface } from '@clr/angular'
|
import { ClrDatagridStringFilterInterface } from '@clr/angular'
|
||||||
import { Observable, of } from 'rxjs'
|
import { Observable, of } from 'rxjs'
|
||||||
@ -9,6 +9,7 @@ import { SasService } from '../services/sas.service'
|
|||||||
import { globals } from '../_globals'
|
import { globals } from '../_globals'
|
||||||
|
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
|
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
|
||||||
|
|
||||||
interface MetaData {
|
interface MetaData {
|
||||||
NAME: any
|
NAME: any
|
||||||
@ -49,7 +50,8 @@ class ValueFilter implements ClrDatagridStringFilterInterface<MetaData> {
|
|||||||
styleUrls: ['./metadata.component.scss'],
|
styleUrls: ['./metadata.component.scss'],
|
||||||
host: {
|
host: {
|
||||||
class: 'content-container'
|
class: 'content-container'
|
||||||
}
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class MetadataComponent implements OnInit {
|
export class MetadataComponent implements OnInit {
|
||||||
metaDataList: Array<any> | undefined
|
metaDataList: Array<any> | undefined
|
||||||
@ -109,26 +111,34 @@ export class MetadataComponent implements OnInit {
|
|||||||
this.metatypesLoading = false
|
this.metatypesLoading = false
|
||||||
this.metaDataSearch = globals.metadata.metaDataSearch
|
this.metaDataSearch = globals.metadata.metaDataSearch
|
||||||
} else {
|
} else {
|
||||||
this.sasService.request('metanav/metatypes', null).then((res: any) => {
|
this.sasService
|
||||||
this.metaDataList = res.types
|
.request('metanav/metatypes', null)
|
||||||
|
.then((res: RequestWrapperResponse) => {
|
||||||
|
this.metaDataList = res.adapterResponse.types
|
||||||
globals.metadata.metaDataList = this.metaDataList
|
globals.metadata.metaDataList = this.metaDataList
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.metatypesLoading = false
|
this.metatypesLoading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
this.sasService.request('metanav/metarepos', null).then((res: any) => {
|
this.sasService
|
||||||
|
.request('metanav/metarepos', null)
|
||||||
|
.then((res: RequestWrapperResponse) => {
|
||||||
let foundation = false
|
let foundation = false
|
||||||
this.repositories = []
|
this.repositories = []
|
||||||
for (let index = 0; index < res.outrepos.length; index++) {
|
for (
|
||||||
this.repositories.push(res.outrepos[index].NAME)
|
let index = 0;
|
||||||
if (res.outrepos[index].NAME === 'Foundation') {
|
index < res.adapterResponse.outrepos.length;
|
||||||
|
index++
|
||||||
|
) {
|
||||||
|
this.repositories.push(res.adapterResponse.outrepos[index].NAME)
|
||||||
|
if (res.adapterResponse.outrepos[index].NAME === 'Foundation') {
|
||||||
foundation = true
|
foundation = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (foundation) {
|
if (foundation) {
|
||||||
this.repository = 'Foundation'
|
this.repository = 'Foundation'
|
||||||
} else {
|
} else {
|
||||||
this.repository = res.outrepos[0].NAME
|
this.repository = res.adapterResponse.outrepos[0].NAME
|
||||||
}
|
}
|
||||||
globals.metadata.metaRepositories = this.repositories
|
globals.metadata.metaRepositories = this.repositories
|
||||||
globals.metadata.selectedRepository = this.repository
|
globals.metadata.selectedRepository = this.repository
|
||||||
@ -183,8 +193,10 @@ export class MetadataComponent implements OnInit {
|
|||||||
const data: any = {
|
const data: any = {
|
||||||
SASControlTable: [{ metatype: $event, repo: this.repository }]
|
SASControlTable: [{ metatype: $event, repo: this.repository }]
|
||||||
}
|
}
|
||||||
this.sasService.request('metanav/metaobjects', data).then((res: any) => {
|
this.sasService
|
||||||
this.metaObjectList = res.objects
|
.request('metanav/metaobjects', data)
|
||||||
|
.then((res: RequestWrapperResponse) => {
|
||||||
|
this.metaObjectList = res.adapterResponse.objects
|
||||||
this.getMetaObjectAttributes(this.metaObjectSize)
|
this.getMetaObjectAttributes(this.metaObjectSize)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.assoTypeSelected = $event
|
this.assoTypeSelected = $event
|
||||||
@ -197,12 +209,16 @@ export class MetadataComponent implements OnInit {
|
|||||||
let data: any = {
|
let data: any = {
|
||||||
SASControlTable: [{ objecturi: $event }]
|
SASControlTable: [{ objecturi: $event }]
|
||||||
}
|
}
|
||||||
this.sasService.request('metanav/metadetails', data).then((res: any) => {
|
this.sasService
|
||||||
this.metaObjectAssociations = res.associations
|
.request('metanav/metadetails', data)
|
||||||
this.root$ = of(this.getAssosiationsCount(res.associations))
|
.then((res: RequestWrapperResponse) => {
|
||||||
|
this.metaObjectAssociations = res.adapterResponse.associations
|
||||||
|
this.root$ = of(
|
||||||
|
this.getAssosiationsCount(res.adapterResponse.associations)
|
||||||
|
)
|
||||||
this.showAcc = true
|
this.showAcc = true
|
||||||
this.showTable = true
|
this.showTable = true
|
||||||
let metaObjectName = res.attributes.find(
|
let metaObjectName = res.adapterResponse.attributes.find(
|
||||||
(x: any) => x.NAME === 'Name'
|
(x: any) => x.NAME === 'Name'
|
||||||
).VALUE
|
).VALUE
|
||||||
this.assoObjectSelected = metaObjectName
|
this.assoObjectSelected = metaObjectName
|
||||||
@ -221,7 +237,7 @@ export class MetadataComponent implements OnInit {
|
|||||||
url + '/object/' + $event.slice(1 + $event.indexOf('\\'))
|
url + '/object/' + $event.slice(1 + $event.indexOf('\\'))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.metaObjectAttributes = res.attributes
|
this.metaObjectAttributes = res.adapterResponse.attributes
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,8 +245,10 @@ export class MetadataComponent implements OnInit {
|
|||||||
let data: any = {
|
let data: any = {
|
||||||
SASControlTable: [{ objecturi: $event }]
|
SASControlTable: [{ objecturi: $event }]
|
||||||
}
|
}
|
||||||
this.sasService.request('metanav/metadetails', data).then((res: any) => {
|
this.sasService
|
||||||
this.metaObjectAttributes = res.attributes
|
.request('metanav/metadetails', data)
|
||||||
|
.then((res: RequestWrapperResponse) => {
|
||||||
|
this.metaObjectAttributes = res.adapterResponse.attributes
|
||||||
this.showTable = true
|
this.showTable = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -244,7 +262,7 @@ export class MetadataComponent implements OnInit {
|
|||||||
details: []
|
details: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let assocObj = assosiationsHash.get(assosiation.ASSOC)
|
let assocObj: any = assosiationsHash.get(assosiation.ASSOC)
|
||||||
assocObj.count++
|
assocObj.count++
|
||||||
assocObj.details.push({
|
assocObj.details.push({
|
||||||
ASSOCURI: assosiation.ASSOCURI,
|
ASSOCURI: assosiation.ASSOCURI,
|
||||||
@ -254,7 +272,7 @@ export class MetadataComponent implements OnInit {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
let assocGrouped: Array<any> = []
|
let assocGrouped: Array<any> = []
|
||||||
assosiationsHash.forEach(function (val, key) {
|
assosiationsHash.forEach(function (val: any, key) {
|
||||||
assocGrouped.push({
|
assocGrouped.push({
|
||||||
ASSOC: key,
|
ASSOC: key,
|
||||||
count: val.count,
|
count: val.count,
|
||||||
@ -294,9 +312,9 @@ export class MetadataComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
return this.sasService
|
return this.sasService
|
||||||
.request('metanav/metadetails', data)
|
.request('metanav/metadetails', data)
|
||||||
.then((res: any) => {
|
.then((res: RequestWrapperResponse) => {
|
||||||
this.showTable = true
|
this.showTable = true
|
||||||
this.metaObjectAttributes = res.attributes
|
this.metaObjectAttributes = res.adapterResponse.attributes
|
||||||
this.assoObjectSelected = asso.NAME
|
this.assoObjectSelected = asso.NAME
|
||||||
let url = this.router.url
|
let url = this.router.url
|
||||||
if (this.objectRoute) {
|
if (this.objectRoute) {
|
||||||
@ -314,7 +332,7 @@ export class MetadataComponent implements OnInit {
|
|||||||
asso.ASSOCURI.slice(1 + asso.ASSOCURI.indexOf('\\'))
|
asso.ASSOCURI.slice(1 + asso.ASSOCURI.indexOf('\\'))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return this.getAssosiationsCount(res.associations)
|
return this.getAssosiationsCount(res.adapterResponse.associations)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
client/src/app/models/AppSettings.ts
Normal file
9
client/src/app/models/AppSettings.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export interface AppSettings {
|
||||||
|
persistSelectedTheme: boolean
|
||||||
|
selectedTheme: AppThemes
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AppThemes {
|
||||||
|
light = 'light',
|
||||||
|
dark = 'dark'
|
||||||
|
}
|
1
client/src/app/models/FileUploadEncoding.ts
Normal file
1
client/src/app/models/FileUploadEncoding.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type FileUploadEncoding = 'UTF-8' | 'WLATIN1'
|
@ -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
|
||||||
}
|
}
|
||||||
|
29
client/src/app/models/ParseParams.interface.ts
Normal file
29
client/src/app/models/ParseParams.interface.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { DcValidator } from '../shared/dc-validator/dc-validator'
|
||||||
|
import { FileUploadEncoding } from './FileUploadEncoding'
|
||||||
|
import { FileUploader } from './FileUploader.class'
|
||||||
|
import { ExcelRule } from './TableData'
|
||||||
|
import XLSX from 'xlsx'
|
||||||
|
|
||||||
|
export interface ParseParams {
|
||||||
|
file: File
|
||||||
|
password?: string
|
||||||
|
dcValidator: DcValidator
|
||||||
|
/**
|
||||||
|
* If workbook is provided, parse function will not run a XLSX.read()
|
||||||
|
* it will use this property instead. So the client must do a file read beforehand
|
||||||
|
*/
|
||||||
|
workbook?: XLSX.WorkBook
|
||||||
|
/**
|
||||||
|
* Parse function will manipulate and return the uploader array which can be provided with files already in the queue
|
||||||
|
* Otherwise new empty instance will be created.
|
||||||
|
*/
|
||||||
|
uploader?: FileUploader
|
||||||
|
headerPks: string[]
|
||||||
|
headerArray: string[]
|
||||||
|
headerShow: string[]
|
||||||
|
timeHeaders: string[]
|
||||||
|
dateHeaders: string[]
|
||||||
|
dateTimeHeaders: string[]
|
||||||
|
xlRules: ExcelRule[]
|
||||||
|
encoding?: FileUploadEncoding
|
||||||
|
}
|
15
client/src/app/models/ParseResult.interface.ts
Normal file
15
client/src/app/models/ParseResult.interface.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { FileUploader } from './FileUploader.class'
|
||||||
|
import FoundRangeInfo from './RangeInfo'
|
||||||
|
|
||||||
|
export interface ParseResult {
|
||||||
|
/**
|
||||||
|
* In case of CSV file, won't be returned
|
||||||
|
*/
|
||||||
|
data?: any[]
|
||||||
|
/**
|
||||||
|
* In case of CSV file, won't be returned
|
||||||
|
*/
|
||||||
|
headerShow?: string[]
|
||||||
|
rangeSheetRes?: FoundRangeInfo
|
||||||
|
uploader: FileUploader
|
||||||
|
}
|
13
client/src/app/models/RangeInfo.ts
Normal file
13
client/src/app/models/RangeInfo.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export default interface FoundRangeInfo {
|
||||||
|
found: boolean
|
||||||
|
sheetName: string
|
||||||
|
rangeStartAddress: string
|
||||||
|
rangeEndAddress: string
|
||||||
|
rangeAddress: string
|
||||||
|
missingHeaders: MissingHeaders[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MissingHeaders {
|
||||||
|
sheetName: string
|
||||||
|
missingHeaders: string[]
|
||||||
|
}
|
13
client/src/app/models/SearchDataExcelResult.interface.ts
Normal file
13
client/src/app/models/SearchDataExcelResult.interface.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { MissingHeaders } from './RangeInfo'
|
||||||
|
|
||||||
|
export interface SearchDataExcelResult {
|
||||||
|
missing?: MissingHeaders[]
|
||||||
|
found?: {
|
||||||
|
data: any
|
||||||
|
arrayData: any[]
|
||||||
|
sheetName: string
|
||||||
|
headers: string[]
|
||||||
|
startAddress?: string
|
||||||
|
endAddress?: string
|
||||||
|
}
|
||||||
|
}
|
@ -7,4 +7,5 @@ export default interface SheetInfo {
|
|||||||
missingHeaders: string[]
|
missingHeaders: string[]
|
||||||
rangeStartRow: number
|
rangeStartRow: number
|
||||||
rangeStartCol: number
|
rangeStartCol: number
|
||||||
|
rangeAddress?: string
|
||||||
}
|
}
|
||||||
|
4
client/src/app/models/UploadFile.ts
Normal file
4
client/src/app/models/UploadFile.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface UploadFileResponse {
|
||||||
|
adapterResponse: any
|
||||||
|
log?: string
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
export interface RequestWrapperResponse<responseType = any> {
|
||||||
|
adapterResponse: responseType
|
||||||
|
log?: string
|
||||||
|
}
|
@ -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 {
|
||||||
|
9
client/src/app/models/sas/editors-restore.model.ts
Normal file
9
client/src/app/models/sas/editors-restore.model.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { BaseSASResponse } from './common/BaseSASResponse'
|
||||||
|
|
||||||
|
export interface EditorsRestoreServiceResponse extends BaseSASResponse {
|
||||||
|
restore_out: RestoreOut[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RestoreOut {
|
||||||
|
LOADREF: string
|
||||||
|
}
|
34
client/src/app/models/sas/editors-stagedata.model.ts
Normal file
34
client/src/app/models/sas/editors-stagedata.model.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { BaseSASResponse } from './common/BaseSASResponse'
|
||||||
|
|
||||||
|
export interface EditorsStageDataSASResponse extends BaseSASResponse {
|
||||||
|
SYSDATE: string
|
||||||
|
SYSTIME: string
|
||||||
|
sasparams: Sasparam[]
|
||||||
|
_DEBUG: string
|
||||||
|
_PROGRAM: string
|
||||||
|
AUTOEXEC: string
|
||||||
|
MF_GETUSER: string
|
||||||
|
SYSCC: string
|
||||||
|
SYSENCODING: string
|
||||||
|
SYSERRORTEXT: string
|
||||||
|
SYSHOSTINFOLONG: string
|
||||||
|
SYSHOSTNAME: string
|
||||||
|
SYSPROCESSID: string
|
||||||
|
SYSPROCESSMODE: string
|
||||||
|
SYSPROCESSNAME: string
|
||||||
|
SYSJOBID: string
|
||||||
|
SYSSCPL: string
|
||||||
|
SYSSITE: string
|
||||||
|
SYSTCPIPHOSTNAME: string
|
||||||
|
SYSUSERID: string
|
||||||
|
SYSVLONG: string
|
||||||
|
SYSWARNINGTEXT: string
|
||||||
|
END_DTTM: string
|
||||||
|
MEMSIZE: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Sasparam {
|
||||||
|
STATUS: string | 'SUCCESS'
|
||||||
|
DSID: string
|
||||||
|
URL: string
|
||||||
|
}
|
19
client/src/app/multi-dataset/multi-dataset-routing.module.ts
Normal file
19
client/src/app/multi-dataset/multi-dataset-routing.module.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { NgModule } from '@angular/core'
|
||||||
|
import { RouterModule, Routes } from '@angular/router'
|
||||||
|
|
||||||
|
import { MultiDatasetRouteComponent } from '../routes/multi-dataset-route/multi-dataset-route.component'
|
||||||
|
import { MultiDatasetComponent } from './multi-dataset.component'
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: MultiDatasetRouteComponent,
|
||||||
|
children: [{ path: '', component: MultiDatasetComponent }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class MultiDatasetRoutingModule {}
|
543
client/src/app/multi-dataset/multi-dataset.component.html
Normal file
543
client/src/app/multi-dataset/multi-dataset.component.html
Normal file
@ -0,0 +1,543 @@
|
|||||||
|
<app-sidebar>
|
||||||
|
<div *ngIf="datasetsLoading" class="my-10-mx-auto text-center">
|
||||||
|
<clr-spinner clrMedium></clr-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="!parsedDatasets.length" class="text-center mb-10">
|
||||||
|
<button
|
||||||
|
(click)="fileUploadInput.click()"
|
||||||
|
id="browse-file"
|
||||||
|
class="btn btn-primary btn-sm"
|
||||||
|
[disabled]="selectedFile !== null || submittingCsv"
|
||||||
|
>
|
||||||
|
Browse file
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
hidden
|
||||||
|
#fileUploadInput
|
||||||
|
id="file-upload"
|
||||||
|
type="file"
|
||||||
|
(change)="onFileChange($event)"
|
||||||
|
multiple
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="parsedDatasets.length && !submittedCsvDatasets.length">
|
||||||
|
<div *ngIf="!excelsSubmitted" class="text-center mb-10">
|
||||||
|
<button (click)="onDiscard()" class="btn btn-danger btn-sm mr-10">
|
||||||
|
Discard
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="onSubmitAll()"
|
||||||
|
id="submit-all"
|
||||||
|
class="btn btn-primary btn-sm"
|
||||||
|
>
|
||||||
|
Submit All
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p cds-text="caption" class="ml-10 mb-10">Found tables:</p>
|
||||||
|
<clr-tree>
|
||||||
|
<clr-tree-node *ngFor="let dataset of parsedDatasets">
|
||||||
|
<button
|
||||||
|
(click)="onParsedDatasetClick(dataset)"
|
||||||
|
class="clr-treenode-link whitespace-nowrap d-flex clr-align-items-center"
|
||||||
|
[class.active]="dataset.active"
|
||||||
|
>
|
||||||
|
<ng-container *ngIf="dataset.submitResult">
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="dataset.submitResult.error"
|
||||||
|
status="danger"
|
||||||
|
shape="exclamation-circle"
|
||||||
|
></cds-icon>
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="dataset.submitResult.success"
|
||||||
|
status="success"
|
||||||
|
shape="check-circle"
|
||||||
|
></cds-icon>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!dataset.submitResult">
|
||||||
|
<ng-container *ngIf="dataset.datasource">
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="!(dataset.datasource.length && dataset.parseResult)"
|
||||||
|
status="danger"
|
||||||
|
shape="exclamation-circle"
|
||||||
|
></cds-icon>
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="dataset.datasource.length && dataset.parseResult"
|
||||||
|
shape="table"
|
||||||
|
></cds-icon>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!dataset.datasource">
|
||||||
|
<cds-icon *ngIf="!dataset.parsingTable" shape="table"></cds-icon>
|
||||||
|
|
||||||
|
<clr-spinner *ngIf="dataset.parsingTable" clrSmall></clr-spinner>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<span class="ml-5"> {{ dataset.libds }} </span>
|
||||||
|
</button>
|
||||||
|
</clr-tree-node>
|
||||||
|
</clr-tree>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="submittedCsvDatasets.length">
|
||||||
|
<p cds-text="caption" class="ml-10 mb-10 mt-10">Submitted tables:</p>
|
||||||
|
<clr-tree>
|
||||||
|
<clr-tree-node *ngFor="let dataset of submittedCsvDatasets">
|
||||||
|
<button
|
||||||
|
(click)="onSubmittedCsvDatasetClick(dataset)"
|
||||||
|
class="clr-treenode-link whitespace-nowrap"
|
||||||
|
[class.active]="dataset.active"
|
||||||
|
>
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="dataset.error"
|
||||||
|
status="danger"
|
||||||
|
shape="exclamation-circle"
|
||||||
|
></cds-icon>
|
||||||
|
<cds-icon
|
||||||
|
*ngIf="dataset.success"
|
||||||
|
status="success"
|
||||||
|
shape="check-circle"
|
||||||
|
></cds-icon>
|
||||||
|
<cds-icon shape="table"></cds-icon>
|
||||||
|
{{ dataset.libds }}
|
||||||
|
</button>
|
||||||
|
</clr-tree-node>
|
||||||
|
</clr-tree>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- <div *ngIf="librariesPaging" class="w-100 text-center">
|
||||||
|
<span class="spinner spinner-sm"> Loading... </span>
|
||||||
|
</div> -->
|
||||||
|
</app-sidebar>
|
||||||
|
|
||||||
|
<div #contentArea class="content-area">
|
||||||
|
<div class="card no-borders h-100 d-flex clr-flex-column">
|
||||||
|
<div
|
||||||
|
class="header-row clr-row justify-content-between clr-justify-content-center w-100 m-0"
|
||||||
|
>
|
||||||
|
<p cds-text="section">Multi Dataset Load</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
*ngIf="selectedFile === null && !submittingCsv"
|
||||||
|
class="no-table-selected pointer-events-none"
|
||||||
|
>
|
||||||
|
<clr-icon
|
||||||
|
shape="upload-cloud"
|
||||||
|
size="40"
|
||||||
|
class="is-info icon-dc-fill"
|
||||||
|
></clr-icon>
|
||||||
|
<p class="text-center color-gray mt-10" cds-text="section">
|
||||||
|
Please upload a file
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="selectedFile !== null || submittingCsv">
|
||||||
|
<ng-container *ngIf="!parsedDatasets.length && selectedFile !== null">
|
||||||
|
<div class="d-flex clr-justify-content-center mt-15">
|
||||||
|
<div class="dataset-input-wrapper">
|
||||||
|
<p cds-text="secondary regular" class="mb-5">
|
||||||
|
Selected file: <strong>{{ selectedFile.name }}</strong>
|
||||||
|
<clr-tooltip>
|
||||||
|
<cds-icon
|
||||||
|
clrTooltipTrigger
|
||||||
|
(click)="onDiscardFile()"
|
||||||
|
shape="trash"
|
||||||
|
status="danger"
|
||||||
|
class="ml-5 cursor-pointer"
|
||||||
|
></cds-icon>
|
||||||
|
<clr-tooltip-content> Discard the file </clr-tooltip-content>
|
||||||
|
</clr-tooltip>
|
||||||
|
</p>
|
||||||
|
<p cds-text="secondary regular" class="mb-20">
|
||||||
|
File size: <strong>{{ selectedFile.sizeMB }} MB</strong>
|
||||||
|
</p>
|
||||||
|
<p cds-text="secondary regular" class="mb-15">
|
||||||
|
Paste or type the list of datasets to upload:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<clr-control-helper class="mb-5"
|
||||||
|
>Each row is one dataset. We will automatically detect tables by
|
||||||
|
the sheetname and populate if any.</clr-control-helper
|
||||||
|
>
|
||||||
|
|
||||||
|
<hot-table
|
||||||
|
hotId="hotInstanceUserDataset"
|
||||||
|
id="hotTableUserDataset"
|
||||||
|
class="mt-15"
|
||||||
|
[afterGetColHeader]="afterGetColHeader"
|
||||||
|
[settings]="hotUserDatasets"
|
||||||
|
[licenseKey]="hotTableLicenseKey"
|
||||||
|
stretchH="all"
|
||||||
|
>
|
||||||
|
</hot-table>
|
||||||
|
|
||||||
|
<div class="dataset-selection-actions text-right mt-10">
|
||||||
|
<button
|
||||||
|
(click)="onStartParsingFile()"
|
||||||
|
id="continue-btn"
|
||||||
|
class="btn btn-primary btn-sm"
|
||||||
|
[disabled]="!matchedDatasets.length"
|
||||||
|
[clrLoading]="uploadLoading"
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container
|
||||||
|
*ngIf="parsedDatasets.length && !submittedCsvDatasets.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
*ngIf="!activeParsedDataset"
|
||||||
|
class="no-table-selected pointer-events-none"
|
||||||
|
>
|
||||||
|
<ng-container *ngIf="fileLoadingState !== FileLoadingState.parsed">
|
||||||
|
<clr-icon
|
||||||
|
shape="process-on-vm"
|
||||||
|
size="40"
|
||||||
|
class="is-info icon-dc-fill"
|
||||||
|
></clr-icon>
|
||||||
|
|
||||||
|
<p class="text-center color-gray mt-10" cds-text="section">
|
||||||
|
{{ fileLoadingState }}...
|
||||||
|
</p>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="fileLoadingState === FileLoadingState.parsed">
|
||||||
|
<clr-icon
|
||||||
|
shape="warning-standard"
|
||||||
|
size="40"
|
||||||
|
class="is-info icon-dc-fill"
|
||||||
|
></clr-icon>
|
||||||
|
<p class="text-center color-gray mt-10" cds-text="section">
|
||||||
|
Please select a dataset on the left to review the data
|
||||||
|
</p>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="activeParsedDataset">
|
||||||
|
<div
|
||||||
|
*ngIf="activeParsedDataset.submitResult"
|
||||||
|
class="d-flex clr-justify-content-between p-10 mt-15 submission-results"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p cds-text="secondary regular" class="mb-10">
|
||||||
|
Submit Status:
|
||||||
|
<span
|
||||||
|
*ngIf="activeParsedDataset.submitResult?.success"
|
||||||
|
class="color-green"
|
||||||
|
><strong>SUCCESS</strong></span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
*ngIf="activeParsedDataset.submitResult?.error"
|
||||||
|
class="color-red"
|
||||||
|
><strong>ERROR</strong></span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
*ngIf="activeParsedDataset.submitResult?.error"
|
||||||
|
cds-text="secondary regular"
|
||||||
|
>
|
||||||
|
Error details:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
*ngIf="
|
||||||
|
!submittingCsv && activeParsedDataset.submitResult?.error
|
||||||
|
"
|
||||||
|
(click)="reSubmitTable(activeParsedDataset)"
|
||||||
|
class="btn btn-primary mt-10"
|
||||||
|
[clrLoading]="submitLoading"
|
||||||
|
>
|
||||||
|
Resubmit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="
|
||||||
|
downloadFile(
|
||||||
|
activeParsedDataset.submitResult.log ||
|
||||||
|
activeParsedDataset.submitResult.success ||
|
||||||
|
activeParsedDataset.submitResult.error
|
||||||
|
)
|
||||||
|
"
|
||||||
|
class="btn btn-primary-outline mt-10"
|
||||||
|
>
|
||||||
|
Download log
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
*ngIf="activeParsedDataset.submitResult?.error"
|
||||||
|
class="error-field mt-15"
|
||||||
|
>
|
||||||
|
<div class="log-wrapper">
|
||||||
|
{{ activeParsedDataset.submitResult?.error | json }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex clr-justify-content-between p-10 mt-15">
|
||||||
|
<div>
|
||||||
|
<p cds-text="secondary regular" class="mb-10">
|
||||||
|
Found in range:
|
||||||
|
|
||||||
|
<ng-container *ngIf="activeParsedDataset.parseResult">
|
||||||
|
<strong
|
||||||
|
>"{{
|
||||||
|
activeParsedDataset.parseResult.rangeSheetRes?.sheetName
|
||||||
|
}}"!{{
|
||||||
|
activeParsedDataset.parseResult.rangeSheetRes
|
||||||
|
?.rangeAddress
|
||||||
|
}}</strong
|
||||||
|
>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!activeParsedDataset.parseResult">
|
||||||
|
<strong *ngIf="!activeParsedDataset.parsingTable"
|
||||||
|
>No data found</strong
|
||||||
|
>
|
||||||
|
|
||||||
|
<span
|
||||||
|
*ngIf="activeParsedDataset.parsingTable"
|
||||||
|
class="d-flex clr-align-items-center"
|
||||||
|
>
|
||||||
|
<strong>Searching for the data...</strong>
|
||||||
|
<clr-spinner class="ml-5" clrSmall></clr-spinner>
|
||||||
|
</span>
|
||||||
|
</ng-container>
|
||||||
|
</p>
|
||||||
|
<p cds-text="secondary regular">
|
||||||
|
Dataset:
|
||||||
|
<strong>
|
||||||
|
<clr-tooltip>
|
||||||
|
<a
|
||||||
|
clrTooltipTrigger
|
||||||
|
[routerLink]="'/editor/' + activeParsedDataset.libds"
|
||||||
|
>{{ activeParsedDataset.libds }}</a
|
||||||
|
>
|
||||||
|
<clr-tooltip-content
|
||||||
|
[clrPosition]="'top-right'"
|
||||||
|
[clrSize]="'sm'"
|
||||||
|
>
|
||||||
|
Click to edit the table
|
||||||
|
</clr-tooltip-content>
|
||||||
|
</clr-tooltip>
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<clr-toggle-wrapper>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
clrToggle
|
||||||
|
[(ngModel)]="activeParsedDataset.includeInSubmission"
|
||||||
|
name="options"
|
||||||
|
[disabled]="
|
||||||
|
!(
|
||||||
|
activeParsedDataset.datasource &&
|
||||||
|
activeParsedDataset.parseResult
|
||||||
|
)
|
||||||
|
"
|
||||||
|
required
|
||||||
|
value="option1"
|
||||||
|
/>
|
||||||
|
<label>Include in submission</label>
|
||||||
|
</clr-toggle-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="isHotHidden" class="text-center w-100">
|
||||||
|
<clr-spinner class="spinner-md"></clr-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hot-table
|
||||||
|
hotId="hotInstance"
|
||||||
|
id="hotTable"
|
||||||
|
class="mt-15"
|
||||||
|
[afterGetColHeader]="afterGetColHeader"
|
||||||
|
[className]="['htDark', 'htCustomHidden']"
|
||||||
|
[licenseKey]="hotTableLicenseKey"
|
||||||
|
[multiColumnSorting]="true"
|
||||||
|
[viewportRowRenderingOffset]="50"
|
||||||
|
[manualColumnResize]="true"
|
||||||
|
[filters]="true"
|
||||||
|
stretchH="all"
|
||||||
|
>
|
||||||
|
</hot-table>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="submittedCsvDatasets.length">
|
||||||
|
<div
|
||||||
|
*ngIf="!activeSubmittedCsvDataset"
|
||||||
|
class="no-table-selected pointer-events-none"
|
||||||
|
>
|
||||||
|
<clr-icon
|
||||||
|
shape="warning-standard"
|
||||||
|
size="40"
|
||||||
|
class="is-info icon-dc-fill"
|
||||||
|
></clr-icon>
|
||||||
|
<p class="text-center color-gray mt-10" cds-text="section">
|
||||||
|
Please select a dataset on the left to review the submit results
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="activeSubmittedCsvDataset">
|
||||||
|
<div class="d-flex clr-justify-content-between p-10">
|
||||||
|
<div>
|
||||||
|
<p cds-text="secondary regular" class="mb-10">
|
||||||
|
Matched with dataset:
|
||||||
|
<strong>
|
||||||
|
<clr-tooltip>
|
||||||
|
<a
|
||||||
|
clrTooltipTrigger
|
||||||
|
[routerLink]="'/editor/' + activeSubmittedCsvDataset.libds"
|
||||||
|
>{{ activeSubmittedCsvDataset.libds }}</a
|
||||||
|
>
|
||||||
|
<clr-tooltip-content
|
||||||
|
[clrPosition]="'top-right'"
|
||||||
|
[clrSize]="'sm'"
|
||||||
|
>
|
||||||
|
Click to edit the table
|
||||||
|
</clr-tooltip-content>
|
||||||
|
</clr-tooltip>
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
<p cds-text="secondary regular" class="mb-10">
|
||||||
|
Status:
|
||||||
|
<span
|
||||||
|
*ngIf="activeSubmittedCsvDataset.success"
|
||||||
|
class="color-green"
|
||||||
|
><strong>SUCCESS</strong></span
|
||||||
|
>
|
||||||
|
<span *ngIf="activeSubmittedCsvDataset.error" class="color-red"
|
||||||
|
><strong>ERROR</strong></span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
*ngIf="activeSubmittedCsvDataset.error"
|
||||||
|
cds-text="secondary regular"
|
||||||
|
>
|
||||||
|
Error details:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
(click)="
|
||||||
|
downloadFile(
|
||||||
|
activeSubmittedCsvDataset.success ||
|
||||||
|
activeSubmittedCsvDataset.error
|
||||||
|
)
|
||||||
|
"
|
||||||
|
class="btn btn-primary-outline mt-10"
|
||||||
|
>
|
||||||
|
Download log
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="activeSubmittedCsvDataset.error" class="error-field mt-15">
|
||||||
|
<div class="log-wrapper">
|
||||||
|
{{ activeSubmittedCsvDataset.error | json }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- <div>
|
||||||
|
<p
|
||||||
|
*ngIf="
|
||||||
|
licenceState.value.viewer_rows_allowed !== Infinity &&
|
||||||
|
hotTable.data &&
|
||||||
|
hotTable.data.length > licenceState.value.viewer_rows_allowed
|
||||||
|
"
|
||||||
|
class="mt-2-i w-100 text-center"
|
||||||
|
>
|
||||||
|
To display more than {{ licenceState.value.viewer_rows_allowed }} rows,
|
||||||
|
contact <contact-link />
|
||||||
|
</p>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<clr-modal [(clrModalOpen)]="showSubmitReasonModal" [clrModalClosable]="false">
|
||||||
|
<h3 class="modal-title">
|
||||||
|
Submit {{ tablesToSubmit.length }}
|
||||||
|
{{ tablesToSubmit.length === 1 ? 'table' : 'tables' }} for approval
|
||||||
|
</h3>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p
|
||||||
|
*ngIf="licenceState.value.submit_rows_limit !== Infinity"
|
||||||
|
cds-text="body"
|
||||||
|
class="licence-limit-notice mt-0 mb-15"
|
||||||
|
>
|
||||||
|
Due to current licence, only
|
||||||
|
{{ licenceState.value.submit_rows_limit }} rows in each file will be
|
||||||
|
submitted. To remove the restriction, contact
|
||||||
|
support@datacontroller.io.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="text-area-full-width">
|
||||||
|
<label for="formFields_8" class="mb-5 d-block">Message</label>
|
||||||
|
<textarea
|
||||||
|
clrTextarea
|
||||||
|
[(ngModel)]="submitReasonMessage"
|
||||||
|
tabindex="0"
|
||||||
|
class="submit-reason"
|
||||||
|
type="text"
|
||||||
|
id="formFields_8"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p cds-text="caption_clean" class="mt-10">
|
||||||
|
Tables will be sent sequentially, logs will be available after all tables
|
||||||
|
are submitted.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-outline"
|
||||||
|
[disabled]="submitLoading"
|
||||||
|
(click)="showSubmitReasonModal = false"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="submit-tables"
|
||||||
|
class="btn btn-primary"
|
||||||
|
[clrLoading]="submitLoading"
|
||||||
|
(click)="submitTables()"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</clr-modal>
|
||||||
|
|
||||||
|
<clr-modal [(clrModalOpen)]="csvSubmitting" [clrModalClosable]="false">
|
||||||
|
<h3 class="modal-title">
|
||||||
|
Submitting {{ csvFiles.length }} CSV
|
||||||
|
{{ csvFiles.length === 1 ? 'file' : 'files' }}
|
||||||
|
</h3>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="text-center">
|
||||||
|
<clr-spinner clrMedium></clr-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p cds-text="caption_clean" class="mt-10 text-center">
|
||||||
|
This will take few moments
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</clr-modal>
|
1095
client/src/app/multi-dataset/multi-dataset.component.ts
Normal file
1095
client/src/app/multi-dataset/multi-dataset.component.ts
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user