Merge pull request 'Refactoring solo pages into a modules' (#19) from tsdoc into development
Reviewed-on: #19 Reviewed-by: allan <allan@4gl.io>
This commit was merged in pull request #19.
	This commit is contained in:
		@@ -97,8 +97,8 @@ jobs:
 | 
			
		||||
        run: |
 | 
			
		||||
          cd client
 | 
			
		||||
          npm -g install cloudron-surfer
 | 
			
		||||
          npm run typedoc
 | 
			
		||||
          surfer put --token ${{ secrets.TSDOC_TOKEN }} --server tsdoc.datacontroller.io ../tsdoc /
 | 
			
		||||
          npm run compodoc:build
 | 
			
		||||
          surfer put --token ${{ secrets.TSDOC_TOKEN }} --server webdoc.datacontroller.io documentation/* /
 | 
			
		||||
 | 
			
		||||
      - name: Upload assets to release
 | 
			
		||||
        run: |
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -10,6 +10,7 @@ client/src/environments/version.ts
 | 
			
		||||
client/cypress/screenshots
 | 
			
		||||
client/cypress/results
 | 
			
		||||
client/cypress/videos
 | 
			
		||||
client/documentation
 | 
			
		||||
cypress.env.json
 | 
			
		||||
sasjsbuild
 | 
			
		||||
sasjsresults
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3442
									
								
								client/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3442
									
								
								client/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "dc-client",
 | 
			
		||||
  "description": "dc-client",
 | 
			
		||||
  "name": "data_controller-client",
 | 
			
		||||
  "description": "DataController Client",
 | 
			
		||||
  "angular-cli": {},
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "node --max_old_space_size=4096 node_modules/@angular/cli/bin/ng serve",
 | 
			
		||||
@@ -29,7 +29,9 @@
 | 
			
		||||
    "cy:run": "cypress run",
 | 
			
		||||
    "audit:prod": "npm audit --omit=dev",
 | 
			
		||||
    "sasdocs": "sasjs doc && ./sasjs/utils/deploydocs.sh",
 | 
			
		||||
    "typedoc": "typedoc --options typedoc.json && cd ../tsdoc"
 | 
			
		||||
    "compodoc:build": "compodoc -p tsconfig.doc.json --name 'Data Controller Client'",
 | 
			
		||||
    "compodoc:build-and-serve": "compodoc -p tsconfig.doc.json -s --name 'Data Controller Client'",
 | 
			
		||||
    "compodoc:serve": "compodoc -s --name 'Data Controller Client'"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
@@ -87,6 +89,8 @@
 | 
			
		||||
    "@angular-eslint/template-parser": "16.0.3",
 | 
			
		||||
    "@angular/cli": "^16.1.0",
 | 
			
		||||
    "@angular/compiler-cli": "^16.1.2",
 | 
			
		||||
    "@babel/plugin-proposal-private-methods": "^7.18.6",
 | 
			
		||||
    "@compodoc/compodoc": "^1.1.21",
 | 
			
		||||
    "@cypress/webpack-preprocessor": "^5.17.1",
 | 
			
		||||
    "@types/core-js": "^2.5.5",
 | 
			
		||||
    "@types/crypto-js": "^4.0.1",
 | 
			
		||||
@@ -119,9 +123,10 @@
 | 
			
		||||
    "rimraf": "3.0.2",
 | 
			
		||||
    "ts-loader": "^9.2.8",
 | 
			
		||||
    "ts-node": "^3.3.0",
 | 
			
		||||
    "typedoc": "^0.23.24",
 | 
			
		||||
    "typedoc": "^0.24.8",
 | 
			
		||||
    "typedoc-plugin-external-module-name": "^4.0.6",
 | 
			
		||||
    "typescript": "~4.9.4",
 | 
			
		||||
    "wait-on": "^6.0.1",
 | 
			
		||||
    "watch": "^1.0.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
import { QueryClause } from './models/TableData'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filtering cache info, to be reused when filtering modal is re-open
 | 
			
		||||
 */
 | 
			
		||||
interface FilterCache {
 | 
			
		||||
  cols: any[]
 | 
			
		||||
  vals: any[]
 | 
			
		||||
@@ -10,12 +13,18 @@ interface FilterCache {
 | 
			
		||||
  query: QueryClause[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filtering cache info in the open viewboxes, to be reused when filtering modal is re-open
 | 
			
		||||
 */
 | 
			
		||||
interface ViewboxCache {
 | 
			
		||||
  [key: number]: {
 | 
			
		||||
    filter: FilterCache
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initial values when no cached values stored
 | 
			
		||||
 */
 | 
			
		||||
export const initFilter: { filter: FilterCache } = {
 | 
			
		||||
  filter: {
 | 
			
		||||
    cols: <any[]>[],
 | 
			
		||||
@@ -28,6 +37,13 @@ export const initFilter: { filter: FilterCache } = {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Cached filtering values across whole app (editor, viewer, viewboxes)
 | 
			
		||||
 * Cached lineage libraries, tables
 | 
			
		||||
 * Cached metadata tree
 | 
			
		||||
 * Cached usernav tree
 | 
			
		||||
 * Cached viyaApi collections, search and selected endpoint
 | 
			
		||||
 */
 | 
			
		||||
export const globals: {
 | 
			
		||||
  rootParam: string
 | 
			
		||||
  editor: any
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
<div class="content-area">
 | 
			
		||||
  <div class="card">
 | 
			
		||||
    <div class="card-header d-flex flex-column justify-content-center">
 | 
			
		||||
      <h3 class="text-center">
 | 
			
		||||
        You succesfully edited table
 | 
			
		||||
        <span class="color-blue font-weight-700">{{ libds }}</span>
 | 
			
		||||
      </h3>
 | 
			
		||||
      <p class="text-center">
 | 
			
		||||
        <b>Please choose from the following actions</b>
 | 
			
		||||
      </p>
 | 
			
		||||
      <div class="row d-flex justify-content-center mt-20">
 | 
			
		||||
        <button
 | 
			
		||||
          class="btn btn-sm btn-outline text-center"
 | 
			
		||||
          (click)="submittedTableScreen()"
 | 
			
		||||
        >
 | 
			
		||||
          Go to submitted table screen
 | 
			
		||||
        </button>
 | 
			
		||||
        <button
 | 
			
		||||
          class="btn btn-sm btn-outline text-center"
 | 
			
		||||
          (click)="viewerTableScreen()"
 | 
			
		||||
        >
 | 
			
		||||
          Go to base table screen
 | 
			
		||||
        </button>
 | 
			
		||||
        <button
 | 
			
		||||
          id="approvalBtn"
 | 
			
		||||
          class="btn btn-sm btn-success-outline text-center"
 | 
			
		||||
          (click)="approveTableScreen()"
 | 
			
		||||
        >
 | 
			
		||||
          Go to approvals screen
 | 
			
		||||
        </button>
 | 
			
		||||
        <button
 | 
			
		||||
          class="btn btn-sm btn-info-outline text-center"
 | 
			
		||||
          (click)="goBack()"
 | 
			
		||||
        >
 | 
			
		||||
          Go back to editor
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
import { AfterViewInit, Component, OnInit } from '@angular/core'
 | 
			
		||||
import { ActivatedRoute, Router } from '@angular/router'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-actions',
 | 
			
		||||
  templateUrl: './actions.component.html',
 | 
			
		||||
  styleUrls: ['./actions.component.scss'],
 | 
			
		||||
  host: {
 | 
			
		||||
    class: 'content-container'
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
export class ActionsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
  public dsid: any
 | 
			
		||||
  public libds: string | undefined
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
    private router: Router
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  public submittedTableScreen() {
 | 
			
		||||
    this.router.navigateByUrl('/stage/' + this.dsid)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public approveTableScreen() {
 | 
			
		||||
    this.router.navigateByUrl('/approve/approveDet/' + this.dsid)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public viewerTableScreen() {
 | 
			
		||||
    this.router.navigateByUrl('/view/data/' + this.libds)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public goBack() {
 | 
			
		||||
    this.router.navigateByUrl('/editor/' + this.libds)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async ngOnInit() {
 | 
			
		||||
    this.dsid = this.route.snapshot.params['dsid']
 | 
			
		||||
    this.libds = this.route.snapshot.params['libds']
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngAfterViewInit() {
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      let approvalBtn: any = window.document.getElementById('approvalBtn')
 | 
			
		||||
      if (!!approvalBtn) {
 | 
			
		||||
        approvalBtn.focus()
 | 
			
		||||
      }
 | 
			
		||||
    }, 700)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -169,7 +169,7 @@
 | 
			
		||||
          <clr-dropdown-menu *clrIfOpen clrPosition="bottom-left">
 | 
			
		||||
            <a [routerLink]="['/view']" clrDropdownItem>VIEW</a>
 | 
			
		||||
            <a [routerLink]="['/home']" clrDropdownItem>EDIT</a>
 | 
			
		||||
            <a [routerLink]="['/submitted']" clrDropdownItem>REVIEW</a>
 | 
			
		||||
            <a [routerLink]="['/review/submitted']" clrDropdownItem>REVIEW</a>
 | 
			
		||||
          </clr-dropdown-menu>
 | 
			
		||||
        </clr-dropdown>
 | 
			
		||||
      </div>
 | 
			
		||||
@@ -192,7 +192,7 @@
 | 
			
		||||
          >EDIT</a
 | 
			
		||||
        >
 | 
			
		||||
        <a
 | 
			
		||||
          [routerLink]="['/submitted']"
 | 
			
		||||
          [routerLink]="['/review/submitted']"
 | 
			
		||||
          [class.active]="
 | 
			
		||||
            router.url.includes('submitted') ||
 | 
			
		||||
            router.url.includes('approve') ||
 | 
			
		||||
@@ -224,7 +224,7 @@
 | 
			
		||||
    <ul class="nav">
 | 
			
		||||
      <li class="nav-item">
 | 
			
		||||
        <a
 | 
			
		||||
          [routerLink]="['/submitted']"
 | 
			
		||||
          [routerLink]="['/review/submitted']"
 | 
			
		||||
          class="nav-link nav-text"
 | 
			
		||||
          routerLinkActive="active"
 | 
			
		||||
          >SUBMIT</a
 | 
			
		||||
@@ -232,15 +232,16 @@
 | 
			
		||||
      </li>
 | 
			
		||||
      <li class="nav-item">
 | 
			
		||||
        <a
 | 
			
		||||
          [routerLink]="['/approve']"
 | 
			
		||||
          [routerLink]="['/review/approve']"
 | 
			
		||||
          class="nav-link nav-text"
 | 
			
		||||
          [class.active]="router.url.includes('approve')"
 | 
			
		||||
          routerLinkActive="active"
 | 
			
		||||
          >APPROVE</a
 | 
			
		||||
        >
 | 
			
		||||
      </li>
 | 
			
		||||
      <li class="nav-item">
 | 
			
		||||
        <a
 | 
			
		||||
          [routerLink]="['/history']"
 | 
			
		||||
          [routerLink]="['/review/history']"
 | 
			
		||||
          class="nav-link nav-text"
 | 
			
		||||
          routerLinkActive="active"
 | 
			
		||||
          >HISTORY</a
 | 
			
		||||
 
 | 
			
		||||
@@ -57,24 +57,15 @@ export class AppComponent {
 | 
			
		||||
    private elementRef: ElementRef
 | 
			
		||||
  ) {
 | 
			
		||||
    this.parseDcAdapterSettings()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Prints app info in the console such as:
 | 
			
		||||
     * - Adapter versions
 | 
			
		||||
     * - App version
 | 
			
		||||
     * - Build timestamp
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    ;(window as any).appinfo = () => {
 | 
			
		||||
      const licenseKeyData = this.licenceService.getLicenseKeyData()
 | 
			
		||||
 | 
			
		||||
      if (licenseKeyData) {
 | 
			
		||||
        const expiry_date = moment(
 | 
			
		||||
          licenseKeyData.valid_until,
 | 
			
		||||
          'YYYY-MM-DD'
 | 
			
		||||
        ).startOf('day')
 | 
			
		||||
        const current_date = moment().startOf('day')
 | 
			
		||||
        const daysToExpiry = expiry_date.diff(current_date, 'days')
 | 
			
		||||
 | 
			
		||||
        licenseKeyData.valid_until += ` (${daysToExpiry} ${
 | 
			
		||||
          daysToExpiry === 1 ? 'day' : 'days'
 | 
			
		||||
        } remaining)`
 | 
			
		||||
 | 
			
		||||
        if (isNaN(daysToExpiry)) licenseKeyData.valid_until = 'Unlimited'
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      console.table({
 | 
			
		||||
        'Adapter version': VERSION.adapterVersion || 'n/a',
 | 
			
		||||
        'App version': (VERSION.tag || '').replace('v', ''),
 | 
			
		||||
@@ -87,7 +78,12 @@ export class AppComponent {
 | 
			
		||||
 | 
			
		||||
    this.subscribeToLicenseEvents()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetches git tag ang git hash from `version.ts` file
 | 
			
		||||
     * It's placed in the user drop down.
 | 
			
		||||
     */
 | 
			
		||||
    this.commitVer = (VERSION.tag || '').replace('v', '') + '.' + VERSION.hash
 | 
			
		||||
 | 
			
		||||
    router.events.subscribe((val) => {
 | 
			
		||||
      this.routeUrl = this.router.url
 | 
			
		||||
 | 
			
		||||
@@ -127,8 +123,10 @@ export class AppComponent {
 | 
			
		||||
    this.subscribeToAppActive()
 | 
			
		||||
    this.subscribeToDemoLimitModal()
 | 
			
		||||
 | 
			
		||||
    /* In Viya streaming apps, content is served within an iframe.  This code
 | 
			
		||||
      makes that iframe "full screen" so it looks like a regular window. */
 | 
			
		||||
    /**
 | 
			
		||||
     * In Viya streaming apps, content is served within an iframe.  This code
 | 
			
		||||
     * makes that iframe "full screen" so it looks like a regular window.
 | 
			
		||||
     */
 | 
			
		||||
    if (window.frameElement) {
 | 
			
		||||
      window.frameElement.setAttribute(
 | 
			
		||||
        'style',
 | 
			
		||||
@@ -143,6 +141,9 @@ export class AppComponent {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Parses adapter settings that are found in the <sasjs> tag inside index.html
 | 
			
		||||
   */
 | 
			
		||||
  private parseDcAdapterSettings() {
 | 
			
		||||
    const sasjsElement = document.querySelector('sasjs')
 | 
			
		||||
 | 
			
		||||
@@ -180,9 +181,14 @@ export class AppComponent {
 | 
			
		||||
    this.appService.sasServiceInit()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Opens licence page with the active licence problem
 | 
			
		||||
   * Problem details are encoded in the url
 | 
			
		||||
   */
 | 
			
		||||
  public licenceProblemDetails(url: string) {
 | 
			
		||||
    this.router.navigateByUrl(url)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Based on string provided we return true, false or null
 | 
			
		||||
   * True -> Compute API
 | 
			
		||||
@@ -199,6 +205,12 @@ export class AppComponent {
 | 
			
		||||
    return value === 'true' || false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Listens for an `demo limit` event that will show the `Feature locked modal`
 | 
			
		||||
   * For exmaple when in editor upload feature is not enabled
 | 
			
		||||
   * When user tries to upload the excel, editor component will trgger this event
 | 
			
		||||
   * And stop the execution of file upload code.
 | 
			
		||||
   */
 | 
			
		||||
  public subscribeToDemoLimitModal() {
 | 
			
		||||
    this.eventService.onDemoLimitModalShow.subscribe((featureName: string) => {
 | 
			
		||||
      this.demoLimitNotice = {
 | 
			
		||||
@@ -208,6 +220,10 @@ export class AppComponent {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Listens for licence events so banner can be displayed.
 | 
			
		||||
   * App is free tier, licence will expire, is expired or is invalid
 | 
			
		||||
   */
 | 
			
		||||
  public subscribeToLicenseEvents() {
 | 
			
		||||
    this.licenceService.isAppFreeTier.subscribe((isAppFreeTier: boolean) => {
 | 
			
		||||
      this.freeTierBanner = isAppFreeTier
 | 
			
		||||
@@ -227,6 +243,10 @@ export class AppComponent {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Listens for an event that will activate od deactivate full application.
 | 
			
		||||
   * Based on licence key prcoessing result
 | 
			
		||||
   */
 | 
			
		||||
  public subscribeToAppActive() {
 | 
			
		||||
    this.licenceService.isAppActivated.subscribe((value: any) => {
 | 
			
		||||
      this.appActive = value
 | 
			
		||||
@@ -248,31 +268,51 @@ export class AppComponent {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * When startupservice request is finished with valid response, this event will
 | 
			
		||||
   * make sure loading screen is gone.
 | 
			
		||||
   */
 | 
			
		||||
  public subscribeToStartupData() {
 | 
			
		||||
    this.eventService.onStartupDataLoaded.subscribe(() => {
 | 
			
		||||
      this.startupDataLoaded = true
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Opens requests modal when requested from event service
 | 
			
		||||
   */
 | 
			
		||||
  public subscribeToRequestsModal() {
 | 
			
		||||
    this.eventService.onRequestsModalOpen.subscribe((value: boolean) => {
 | 
			
		||||
      this.requestsModal = true
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Closes abort modal with matching ID (there could be multiple abort modals open)
 | 
			
		||||
   */
 | 
			
		||||
  public closeAbortModal(abortId: number) {
 | 
			
		||||
    let abortIndex = this.sasjsAborts.findIndex((abort) => abort.id === abortId)
 | 
			
		||||
    this.sasjsAborts.splice(abortIndex, 1)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Toggles sidebar when requested from event service
 | 
			
		||||
   */
 | 
			
		||||
  public toggleSidebar() {
 | 
			
		||||
    this.eventService.toggleSidebar()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether or not current route includes the route from param
 | 
			
		||||
   * @param route route to check
 | 
			
		||||
   */
 | 
			
		||||
  public isMainRoute(route: string): boolean {
 | 
			
		||||
    return this.router.url.includes(route)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Opens a page for updating the licence.
 | 
			
		||||
   */
 | 
			
		||||
  public openLicencingPage() {
 | 
			
		||||
    this.router.navigateByUrl('/licensing/update')
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,33 +11,16 @@ import { NotFoundComponent } from './not-found/not-found.component'
 | 
			
		||||
 | 
			
		||||
import { SasStoreService } from './services/sas-store.service'
 | 
			
		||||
import { SharedModule } from './shared/shared.module'
 | 
			
		||||
// import { EditorComponent } from './editor/editor.component'
 | 
			
		||||
import { ActionsComponent } from './actions/actions.component'
 | 
			
		||||
 | 
			
		||||
import { AppSharedModule } from './app-shared.module'
 | 
			
		||||
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
 | 
			
		||||
import { ApproveComponent } from './approve/approve.component'
 | 
			
		||||
import { DeployComponent } from './deploy/deploy.component'
 | 
			
		||||
import { AutomaticComponent } from './deploy/sections/automatic/automatic.component'
 | 
			
		||||
import { ManualComponent } from './deploy/sections/manual/manual.component'
 | 
			
		||||
import { SasjsConfiguratorComponent } from './deploy/sections/sasjs-configurator/sasjs-configurator.component'
 | 
			
		||||
import { GroupComponent } from './group/group.component'
 | 
			
		||||
import { HistoryComponent } from './history/history.component'
 | 
			
		||||
import { LicensingComponent } from './licensing/licensing.component'
 | 
			
		||||
import { LineageComponent } from './lineage/lineage.component'
 | 
			
		||||
import { MetadataComponent } from './metadata/metadata.component'
 | 
			
		||||
import { PipesModule } from './pipes/pipes.module'
 | 
			
		||||
import { RoleComponent } from './role/role.component'
 | 
			
		||||
import { ApproveRouteComponent } from './routes/approve-route/approve-route.component'
 | 
			
		||||
import { HistoryRouteComponent } from './routes/history-route/history-route.component'
 | 
			
		||||
import { ReviewRouteComponent } from './routes/review-route/review-route.component'
 | 
			
		||||
import { LicensingGuard } from './routes/licensing.guard'
 | 
			
		||||
import { UsernavRouteComponent } from './routes/usernav-route/usernav-route.component'
 | 
			
		||||
import { AppService } from './services/app.service'
 | 
			
		||||
import { InfoModalComponent } from './shared/abort-modal/info-modal.component'
 | 
			
		||||
import { RequestsModalComponent } from './shared/requests-modal/requests-modal.component'
 | 
			
		||||
import { SubmitterComponent } from './submitter/submitter.component'
 | 
			
		||||
import { UserComponent } from './user/user.component'
 | 
			
		||||
import { HomeModule } from './home/home.module'
 | 
			
		||||
import { SystemComponent } from './system/system.component'
 | 
			
		||||
import { DirectivesModule } from './directives/directives.module'
 | 
			
		||||
import { ViyaApiExplorerComponent } from './viya-api-explorer/viya-api-explorer.component'
 | 
			
		||||
import { NgxJsonViewerModule } from 'ngx-json-viewer'
 | 
			
		||||
@@ -46,27 +29,11 @@ import { NgxJsonViewerModule } from 'ngx-json-viewer'
 | 
			
		||||
  declarations: [
 | 
			
		||||
    AppComponent,
 | 
			
		||||
    NotFoundComponent,
 | 
			
		||||
    ApproveComponent,
 | 
			
		||||
    ApproveDetailsComponent,
 | 
			
		||||
    ActionsComponent,
 | 
			
		||||
    HistoryComponent,
 | 
			
		||||
    LineageComponent,
 | 
			
		||||
    SubmitterComponent,
 | 
			
		||||
    ApproveRouteComponent,
 | 
			
		||||
    HistoryRouteComponent,
 | 
			
		||||
    MetadataComponent,
 | 
			
		||||
    ReviewRouteComponent,
 | 
			
		||||
    ReviewRouteComponent,
 | 
			
		||||
    UsernavRouteComponent,
 | 
			
		||||
    UserComponent,
 | 
			
		||||
    GroupComponent,
 | 
			
		||||
    RoleComponent,
 | 
			
		||||
    RequestsModalComponent,
 | 
			
		||||
    DeployComponent,
 | 
			
		||||
    InfoModalComponent,
 | 
			
		||||
    LicensingComponent,
 | 
			
		||||
    ManualComponent,
 | 
			
		||||
    AutomaticComponent,
 | 
			
		||||
    SasjsConfiguratorComponent,
 | 
			
		||||
    SystemComponent,
 | 
			
		||||
    ViyaApiExplorerComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
@@ -84,7 +51,7 @@ import { NgxJsonViewerModule } from 'ngx-json-viewer'
 | 
			
		||||
    DirectivesModule,
 | 
			
		||||
    NgxJsonViewerModule
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [AppService, SasStoreService, ApproveComponent, LicensingGuard],
 | 
			
		||||
  providers: [AppService, SasStoreService, LicensingGuard],
 | 
			
		||||
  bootstrap: [AppComponent]
 | 
			
		||||
})
 | 
			
		||||
export class AppModule {}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,22 +7,20 @@ import { ModuleWithProviders } from '@angular/core'
 | 
			
		||||
import { Routes, RouterModule } from '@angular/router'
 | 
			
		||||
 | 
			
		||||
import { HomeComponent } from './home/home.component'
 | 
			
		||||
import { ApproveComponent } from './approve/approve.component'
 | 
			
		||||
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
 | 
			
		||||
import { ActionsComponent } from './actions/actions.component'
 | 
			
		||||
import { HistoryComponent } from './history/history.component'
 | 
			
		||||
import { NotFoundComponent } from './not-found/not-found.component'
 | 
			
		||||
import { SubmitterComponent } from './submitter/submitter.component'
 | 
			
		||||
 | 
			
		||||
import { ApproveRouteComponent } from './routes/approve-route/approve-route.component'
 | 
			
		||||
import { DeployComponent } from './deploy/deploy.component'
 | 
			
		||||
import { LicensingComponent } from './licensing/licensing.component'
 | 
			
		||||
import { LicensingGuard } from './routes/licensing.guard'
 | 
			
		||||
import { ReviewRouteComponent } from './routes/review-route/review-route.component'
 | 
			
		||||
import { StageModule } from './stage/stage.module'
 | 
			
		||||
import { EditorModule } from './editor/editor.module'
 | 
			
		||||
import { ViewerModule } from './viewer/viewer.module'
 | 
			
		||||
import { SystemComponent } from './system/system.component'
 | 
			
		||||
import { ReviewModule } from './review/review.module'
 | 
			
		||||
import { DeployModule } from './deploy/deploy.module'
 | 
			
		||||
import { LicensingModule } from './licensing/licensing.module'
 | 
			
		||||
import { SystemModule } from './system/system.module'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defining routes
 | 
			
		||||
 */
 | 
			
		||||
export const ROUTES: Routes = [
 | 
			
		||||
  { path: '', redirectTo: 'home', pathMatch: 'full' },
 | 
			
		||||
  {
 | 
			
		||||
@@ -30,23 +28,28 @@ export const ROUTES: Routes = [
 | 
			
		||||
    loadChildren: () => ViewerModule
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'approve',
 | 
			
		||||
    component: ApproveRouteComponent,
 | 
			
		||||
    /**
 | 
			
		||||
     * Load review module (approve, history, submitted)
 | 
			
		||||
     */
 | 
			
		||||
    path: 'review',
 | 
			
		||||
    component: ReviewRouteComponent,
 | 
			
		||||
    children: [
 | 
			
		||||
      { path: '', pathMatch: 'full', redirectTo: 'toapprove' },
 | 
			
		||||
      { path: 'toapprove', component: ApproveComponent },
 | 
			
		||||
      { path: 'approveDet/:tableId', component: ApproveDetailsComponent },
 | 
			
		||||
      { path: 'submitted', component: SubmitterComponent }
 | 
			
		||||
      {
 | 
			
		||||
        path: '',
 | 
			
		||||
        loadChildren: () => ReviewModule
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'licensing/:action',
 | 
			
		||||
    component: LicensingComponent,
 | 
			
		||||
    canActivate: [LicensingGuard],
 | 
			
		||||
    canDeactivate: [LicensingGuard]
 | 
			
		||||
    path: 'licensing',
 | 
			
		||||
    loadChildren: () => LicensingModule
 | 
			
		||||
  },
 | 
			
		||||
  { path: 'home', component: HomeComponent },
 | 
			
		||||
  {
 | 
			
		||||
    /**
 | 
			
		||||
     * Load editor module with subroutes
 | 
			
		||||
     */
 | 
			
		||||
    path: 'editor',
 | 
			
		||||
    loadChildren: () => EditorModule
 | 
			
		||||
  },
 | 
			
		||||
@@ -54,16 +57,20 @@ export const ROUTES: Routes = [
 | 
			
		||||
    path: 'stage',
 | 
			
		||||
    loadChildren: () => StageModule
 | 
			
		||||
  },
 | 
			
		||||
  { path: 'system', component: SystemComponent },
 | 
			
		||||
  { path: 'actions/:libds/:dsid', component: ActionsComponent },
 | 
			
		||||
  { path: 'history', component: HistoryComponent },
 | 
			
		||||
  { path: 'submitted', component: SubmitterComponent },
 | 
			
		||||
  { path: 'submitted/:tableId', component: SubmitterComponent },
 | 
			
		||||
  { path: 'deploy', component: DeployComponent },
 | 
			
		||||
  { path: 'deploy/manualdeploy', component: DeployComponent },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'system',
 | 
			
		||||
    loadChildren: () => SystemModule
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'deploy',
 | 
			
		||||
    loadChildren: () => DeployModule
 | 
			
		||||
  },
 | 
			
		||||
  { path: '**', component: NotFoundComponent }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Exporting routes
 | 
			
		||||
 */
 | 
			
		||||
export const ROUTING: ModuleWithProviders<RouterModule> = RouterModule.forRoot(
 | 
			
		||||
  ROUTES,
 | 
			
		||||
  { useHash: true }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								client/src/app/deploy/deploy-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								client/src/app/deploy/deploy-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router'
 | 
			
		||||
import { DeployComponent } from './deploy.component'
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
  { path: '', component: DeployComponent },
 | 
			
		||||
  { path: 'manualdeploy', component: DeployComponent }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forChild(routes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class DeployRoutingModule {}
 | 
			
		||||
@@ -78,6 +78,9 @@ export class DeployComponent implements OnInit {
 | 
			
		||||
    this.setDeployDefaults()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Setting default values used for deploy request
 | 
			
		||||
   */
 | 
			
		||||
  public setDeployDefaults() {
 | 
			
		||||
    this.dcPath = this.dcAdapterSettings?.dcPath || ''
 | 
			
		||||
    this.selectedAdminGroup = this.dcAdapterSettings?.adminGroup || ''
 | 
			
		||||
@@ -86,6 +89,9 @@ export class DeployComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Accepting terms of service shows next screen
 | 
			
		||||
   */
 | 
			
		||||
  public termsAgreeChange() {
 | 
			
		||||
    if (!this.autodeploy) {
 | 
			
		||||
      this.getAdminGroups()
 | 
			
		||||
@@ -94,6 +100,9 @@ export class DeployComponent implements OnInit {
 | 
			
		||||
    this.step++
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Fetches admin groups from VIYA to be selected for a backend deploy
 | 
			
		||||
   */
 | 
			
		||||
  public getAdminGroups() {
 | 
			
		||||
    fetch(
 | 
			
		||||
      this.sasJsConfig.serverUrl + '/identities/groups?sortBy=name&limit=5000',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								client/src/app/deploy/deploy.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								client/src/app/deploy/deploy.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { CommonModule } from '@angular/common'
 | 
			
		||||
import { DeployComponent } from './deploy.component'
 | 
			
		||||
import { AutomaticComponent } from './sections/automatic/automatic.component'
 | 
			
		||||
import { ManualComponent } from './sections/manual/manual.component'
 | 
			
		||||
import { SasjsConfiguratorComponent } from './sections/sasjs-configurator/sasjs-configurator.component'
 | 
			
		||||
import { ClarityModule } from '@clr/angular'
 | 
			
		||||
import { FormsModule } from '@angular/forms'
 | 
			
		||||
import { DeployRoutingModule } from './deploy-routing.module'
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    DeployComponent,
 | 
			
		||||
    AutomaticComponent,
 | 
			
		||||
    ManualComponent,
 | 
			
		||||
    SasjsConfiguratorComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [CommonModule, FormsModule, ClarityModule, DeployRoutingModule]
 | 
			
		||||
})
 | 
			
		||||
export class DeployModule {}
 | 
			
		||||
@@ -55,6 +55,13 @@ export class AutomaticComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Executes sas.json file to deploy the backend
 | 
			
		||||
   * Method will first try to run the `auto deploy`
 | 
			
		||||
   * If that fails the rest of the code is ignored.
 | 
			
		||||
   * If request is successfull, method will continue to try
 | 
			
		||||
   * to create database if checkbox is toggled on
 | 
			
		||||
   */
 | 
			
		||||
  public async executeJson() {
 | 
			
		||||
    this.autodeploying = true
 | 
			
		||||
    this.isSubmittingJson = true
 | 
			
		||||
@@ -99,6 +106,9 @@ export class AutomaticComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Runs the `makedata` request sending the ADMIN and DCPATH values
 | 
			
		||||
   */
 | 
			
		||||
  public createDatabase() {
 | 
			
		||||
    let data = {
 | 
			
		||||
      fromjs: [
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,9 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * FIXME: Remove
 | 
			
		||||
   */
 | 
			
		||||
  public async executableContext() {
 | 
			
		||||
    // getExecutableContexts now need AuthConfig parameter which we don't have on web
 | 
			
		||||
    // this.contextsLoading = true
 | 
			
		||||
@@ -65,10 +68,16 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    // this.contextsLoading = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes sas.json file attached to the input
 | 
			
		||||
   */
 | 
			
		||||
  public clearUploadInput(event: Event) {
 | 
			
		||||
    this.deployService.clearUploadInput(event)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Reads attached SAS file to be sent to sas for execution (backend deploy)
 | 
			
		||||
   */
 | 
			
		||||
  public onSasFileChange(event: any) {
 | 
			
		||||
    this.preloadedFile = false
 | 
			
		||||
 | 
			
		||||
@@ -93,12 +102,18 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    fileReader.readAsText(file)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Reads attached JSON file to be sent to sas for execution (backend deploy)
 | 
			
		||||
   */
 | 
			
		||||
  public async onJsonFileChange(event: any) {
 | 
			
		||||
    let file = event.target.files[0]
 | 
			
		||||
 | 
			
		||||
    this.jsonFile = await this.deployService.readFile(file)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Appending precode lines to the attached sas or json file for backend deploy
 | 
			
		||||
   */
 | 
			
		||||
  public addPrecodeLines() {
 | 
			
		||||
    let headerLines = [
 | 
			
		||||
      `%let context=${this.selectedContext};`,
 | 
			
		||||
@@ -110,6 +125,9 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    this.linesOfCode.unshift(...headerLines)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Downloadng file with precode included
 | 
			
		||||
   */
 | 
			
		||||
  public downloadSasPrecodeFile() {
 | 
			
		||||
    let linesAsText = this.linesOfCode.join('\n')
 | 
			
		||||
    let filename = this.fileName.split('.')[0]
 | 
			
		||||
@@ -117,6 +135,9 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    this.downloadFile(linesAsText, filename, 'sas')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Used for downloading log and repsonse as a file
 | 
			
		||||
   */
 | 
			
		||||
  public downloadFile(
 | 
			
		||||
    content: any,
 | 
			
		||||
    filename: string,
 | 
			
		||||
@@ -125,10 +146,17 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    this.deployService.downloadFile(content, filename, extension)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Saving dcpath to localstorage
 | 
			
		||||
   * FIXME: maybe it'snot necessary
 | 
			
		||||
   */
 | 
			
		||||
  public saveDcPath() {
 | 
			
		||||
    localStorage.setItem('deploy_dc_loc', this.dcPath)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Send sas.json to be executed (deploying backend)
 | 
			
		||||
   */
 | 
			
		||||
  public async executeJson() {
 | 
			
		||||
    this.isSubmittingJson = true
 | 
			
		||||
 | 
			
		||||
@@ -162,6 +190,9 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    this.isSubmittingJson = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Send sas file to be executed (deploying backend)
 | 
			
		||||
   */
 | 
			
		||||
  public async executeSAS() {
 | 
			
		||||
    this.executingScript = true
 | 
			
		||||
    this.jobLog = ''
 | 
			
		||||
@@ -194,6 +225,10 @@ export class ManualComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Running makedata service
 | 
			
		||||
   * @param newTab open and run in new tab
 | 
			
		||||
   */
 | 
			
		||||
  public createDatabase(newTab: boolean = true) {
 | 
			
		||||
    if (newTab) {
 | 
			
		||||
      let url =
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import { ServerType } from '@sasjs/utils/types/serverType'
 | 
			
		||||
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
 | 
			
		||||
import { SASGroup } from 'src/app/models/sas/public-getgroups.model'
 | 
			
		||||
import { SASjsApiServerInfo } from 'src/app/models/sasjs-api/SASjsApiServerInfo.model'
 | 
			
		||||
import { HelperService } from 'src/app/services/helper.service'
 | 
			
		||||
import { SasService } from 'src/app/services/sas.service'
 | 
			
		||||
import { SasjsService } from 'src/app/services/sasjs.service'
 | 
			
		||||
 | 
			
		||||
@@ -51,6 +50,9 @@ export class SasjsConfiguratorComponent implements OnInit {
 | 
			
		||||
    this.getServerInfo()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Fethes the sasjs server instance info
 | 
			
		||||
   */
 | 
			
		||||
  getServerInfo() {
 | 
			
		||||
    this.sasjsService
 | 
			
		||||
      .getServerInfo()
 | 
			
		||||
@@ -59,6 +61,9 @@ export class SasjsConfiguratorComponent implements OnInit {
 | 
			
		||||
      })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Fetches user groups from the `usernav/usergroupsbymember` service
 | 
			
		||||
   */
 | 
			
		||||
  getUserGroups() {
 | 
			
		||||
    this.loading = true
 | 
			
		||||
 | 
			
		||||
@@ -99,6 +104,9 @@ export class SasjsConfiguratorComponent implements OnInit {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creating database
 | 
			
		||||
   */
 | 
			
		||||
  makeData() {
 | 
			
		||||
    // const _debug = "&_debug=131"; //debug on
 | 
			
		||||
    const _debug = ' ' //debug off
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,9 @@ export class DragNdropDirective {
 | 
			
		||||
  @Output() fileDropped = new EventEmitter<any>()
 | 
			
		||||
  @Output() fileDraggedOver = new EventEmitter<any>()
 | 
			
		||||
 | 
			
		||||
  // Dragover listener
 | 
			
		||||
  /**
 | 
			
		||||
   * Dragover listener
 | 
			
		||||
   */
 | 
			
		||||
  @HostListener('dragover', ['$event'])
 | 
			
		||||
  onDragOver(event: any) {
 | 
			
		||||
    event.preventDefault()
 | 
			
		||||
@@ -26,7 +28,9 @@ export class DragNdropDirective {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Dragleave listener
 | 
			
		||||
  /**
 | 
			
		||||
   * Dragleave listener
 | 
			
		||||
   */
 | 
			
		||||
  @HostListener('dragleave', ['$event'])
 | 
			
		||||
  public onDragLeave(event: any) {
 | 
			
		||||
    event.preventDefault()
 | 
			
		||||
@@ -34,7 +38,9 @@ export class DragNdropDirective {
 | 
			
		||||
    this.fileOver = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Drop listener
 | 
			
		||||
  /**
 | 
			
		||||
   * Drop listener
 | 
			
		||||
   */
 | 
			
		||||
  @HostListener('drop', ['$event'])
 | 
			
		||||
  public ondrop(event: any) {
 | 
			
		||||
    event.preventDefault()
 | 
			
		||||
@@ -48,6 +54,9 @@ export class DragNdropDirective {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks wether dragging element contain files
 | 
			
		||||
   */
 | 
			
		||||
  private containsFiles(event: any) {
 | 
			
		||||
    if (event && event.dataTransfer && event.dataTransfer.types) {
 | 
			
		||||
      for (let i = 0; i < event.dataTransfer.types.length; i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@ export class FileDropDirective {
 | 
			
		||||
    this.element = element
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Dragging element drop event
 | 
			
		||||
   */
 | 
			
		||||
  @HostListener('drop', ['$event'])
 | 
			
		||||
  onDrop(event: DragEvent): void {
 | 
			
		||||
    this._preventAndStop(event)
 | 
			
		||||
@@ -39,6 +42,9 @@ export class FileDropDirective {
 | 
			
		||||
    this.fileDrop.emit(fileList)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Dragging element drag over event
 | 
			
		||||
   */
 | 
			
		||||
  @HostListener('dragover', ['$event'])
 | 
			
		||||
  onDragOver(event: DragEvent): void {
 | 
			
		||||
    this._preventAndStop(event)
 | 
			
		||||
@@ -59,6 +65,10 @@ export class FileDropDirective {
 | 
			
		||||
    this.fileOver.emit(false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prevent propagation trough elements and stop default behavior
 | 
			
		||||
   * For particular event
 | 
			
		||||
   */
 | 
			
		||||
  protected _preventAndStop(event: MouseEvent): void {
 | 
			
		||||
    event.preventDefault()
 | 
			
		||||
    event.stopPropagation()
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,9 @@ export class FileSelectDirective {
 | 
			
		||||
    this.element = element
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks if files exist in the input after input change
 | 
			
		||||
   */
 | 
			
		||||
  isEmptyAfterSelection(): boolean {
 | 
			
		||||
    return !!this.element.nativeElement.attributes.multiple
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
export interface RowValidation {
 | 
			
		||||
  valid: boolean
 | 
			
		||||
  invalidError: string
 | 
			
		||||
  rowNumber?: number
 | 
			
		||||
  colName?: string
 | 
			
		||||
  value?: string
 | 
			
		||||
}
 | 
			
		||||
@@ -59,6 +59,12 @@ export class EditRecordComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Runs native HOT validator against cell value
 | 
			
		||||
   * @param cellValidation column rules
 | 
			
		||||
   * @param cellValue value in the cell that is beign validated
 | 
			
		||||
   * @returns Promise boolean - wether valid or invalid
 | 
			
		||||
   */
 | 
			
		||||
  async validateRecordCol(
 | 
			
		||||
    cellValidation: any,
 | 
			
		||||
    cellValue: any
 | 
			
		||||
@@ -74,6 +80,12 @@ export class EditRecordComponent implements OnInit {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Fired when date field in the record change
 | 
			
		||||
   * Function will parse date and format to string
 | 
			
		||||
   * @param date picker value
 | 
			
		||||
   * @param colKey column name (key)
 | 
			
		||||
   */
 | 
			
		||||
  recordDateChange(date: Date, colKey: string) {
 | 
			
		||||
    let cellValidation = this.currentRecordValidator?.getRule(colKey)
 | 
			
		||||
    let format = cellValidation ? cellValidation.dateFormat : ''
 | 
			
		||||
@@ -82,24 +94,38 @@ export class EditRecordComponent implements OnInit {
 | 
			
		||||
      this.currentRecord[colKey] = moment(date).format(format)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isRecordModalInvalid(): boolean {
 | 
			
		||||
    return this.currentRecordInvalidCols.length > 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Close edit record modal and apply changes by emitting output event
 | 
			
		||||
   */
 | 
			
		||||
  confirmRecordEdit() {
 | 
			
		||||
    if (this.currentRecordInvalidCols.length < 1) {
 | 
			
		||||
      this.onRecordChange.emit(this.currentRecord)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Close edit record modal without applying the changes
 | 
			
		||||
   */
 | 
			
		||||
  closeRecordEdit() {
 | 
			
		||||
    this.onRecordEditClose.emit()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Emitting output event when dropdown (autocomplete) input in any col change
 | 
			
		||||
   * @param colName column name (key)
 | 
			
		||||
   * @param col column index
 | 
			
		||||
   */
 | 
			
		||||
  onRecordDropdownChange(colName: string, col: number) {
 | 
			
		||||
    this.onRecordDropdownChanged.emit({ colName, col })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Emitting output event when input is focused (clicked on) so we can run a `dynamic cell validation`
 | 
			
		||||
   * Since that bit must be run from the parent component (editor.component)
 | 
			
		||||
   * Result is then applied in the `cellValidation` variable and automatically updated in this component.
 | 
			
		||||
   * @param event input event
 | 
			
		||||
   * @param colName column name (key)
 | 
			
		||||
   */
 | 
			
		||||
  onRecordInputFocus(event: any, colName: number) {
 | 
			
		||||
    this.onRecordInputFocused.emit({ event, colName })
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,15 @@ import { Subject, Subscription } from 'rxjs'
 | 
			
		||||
import { SasStoreService } from '../services/sas-store.service'
 | 
			
		||||
 | 
			
		||||
import * as XLSX from '@sheet/crypto'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used in combination with buffer
 | 
			
		||||
 */
 | 
			
		||||
const iconv = require('iconv-lite')
 | 
			
		||||
/**
 | 
			
		||||
 * In combination with `iconv` is used for encoding json data captured with sheet js from excel file into a file again
 | 
			
		||||
 * Which will be send to backend
 | 
			
		||||
 */
 | 
			
		||||
const Buffer = require('buffer/').Buffer
 | 
			
		||||
type AOA = any[][]
 | 
			
		||||
 | 
			
		||||
@@ -374,6 +382,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    this.setRestrictions()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepare feature restrictions based on licence key
 | 
			
		||||
   */
 | 
			
		||||
  private parseRestrictions() {
 | 
			
		||||
    this.restrictions.restrictAddRecord =
 | 
			
		||||
      this.licenceState.value.addRecord === false
 | 
			
		||||
@@ -383,6 +394,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      this.licenceState.value.fileUpload === false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Applying prepared restrictions
 | 
			
		||||
   * @param overrideRestrictions can be used to apply and override specific restrictions
 | 
			
		||||
   */
 | 
			
		||||
  private setRestrictions(overrideRestrictions?: EditorRestrictions) {
 | 
			
		||||
    if (overrideRestrictions) {
 | 
			
		||||
      this.restrictions = {
 | 
			
		||||
@@ -402,6 +417,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Disabling add row button based on wether rows limit is present
 | 
			
		||||
   */
 | 
			
		||||
  private checkRowLimit() {
 | 
			
		||||
    if (this.columnLevelSecurityFlag) return
 | 
			
		||||
 | 
			
		||||
@@ -416,12 +434,19 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resetting filter variables
 | 
			
		||||
   */
 | 
			
		||||
  public resetFilter() {
 | 
			
		||||
    if (this.queryFilterCompList.first) {
 | 
			
		||||
      this.queryFilterCompList.first.resetFilter()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Openning file upload modal
 | 
			
		||||
   * If feature is locked, `feature locked` modal will be shown
 | 
			
		||||
   */
 | 
			
		||||
  public onShowUploadModal() {
 | 
			
		||||
    if (this.restrictions.restrictFileUpload) {
 | 
			
		||||
      this.eventService.showDemoLimitModal('File Upload')
 | 
			
		||||
@@ -439,6 +464,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    if (!this.uploadPreview) this.showUploadModal = true
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Called by FileDropDirective
 | 
			
		||||
   * @param e true if file is dragged over the drop zone
 | 
			
		||||
   */
 | 
			
		||||
  public fileOverBase(e: boolean): void {
 | 
			
		||||
    this.hasBaseDropZoneOver = e
 | 
			
		||||
  }
 | 
			
		||||
@@ -620,6 +649,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    return returnObj
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * When excel is password protected we will display the password promppt for user to type password in.
 | 
			
		||||
   * @returns Password user input or undefined if discarded by user
 | 
			
		||||
   */
 | 
			
		||||
  public promptExcelPassword(): Promise<string | undefined> {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
      this.filePasswordModal = true
 | 
			
		||||
@@ -645,6 +678,13 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Parses attached file, to be uploaded
 | 
			
		||||
   * If attached file is CSV it will be send to backend straight away
 | 
			
		||||
   * If attached file is EXCEL it will be displayed in the table, in preview mode
 | 
			
		||||
   * @param event file drop event
 | 
			
		||||
   * @param dropped whether it's dropped or added by browse button
 | 
			
		||||
   */
 | 
			
		||||
  public getFileDesc(event: any, dropped: boolean = false) {
 | 
			
		||||
    this.excelUploadState = 'Loading'
 | 
			
		||||
    this.excelFileParsing = true
 | 
			
		||||
@@ -1010,6 +1050,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Submits attached excel file that is in preview mode
 | 
			
		||||
   */
 | 
			
		||||
  public submitExcel() {
 | 
			
		||||
    if (this.licenceState.value.submit_rows_limit !== Infinity) {
 | 
			
		||||
      this.submitLimitNotice = true
 | 
			
		||||
@@ -1019,6 +1062,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    this.getFile()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * This method will run validations and upload all of the pending files that are in the uploader queue
 | 
			
		||||
   */
 | 
			
		||||
  public getFile() {
 | 
			
		||||
    if (this.checkInvalid()) {
 | 
			
		||||
      this.eventService.showAbortModal(null, 'Invalid values are present.')
 | 
			
		||||
@@ -1091,6 +1137,9 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * After excel file is attached and parsed, this function will display it's content in the HOT table in read only mode
 | 
			
		||||
   */
 | 
			
		||||
  public getPendingExcelPreview() {
 | 
			
		||||
    this.queryTextSaved = this.queryText
 | 
			
		||||
    this.queryText = ''
 | 
			
		||||
@@ -1142,46 +1191,12 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      this.excelFileParsing = false
 | 
			
		||||
      this.excelUploadState = null
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This is half validation feature to speed up file upload
 | 
			
		||||
     * Currently disabled but will leave it here in case it needs to be re-enabled
 | 
			
		||||
     */
 | 
			
		||||
    // this.excelUploadState = 'Validating-DQ'
 | 
			
		||||
 | 
			
		||||
    // this.validateRowsOnPendingExcel(
 | 
			
		||||
    //   async (rowValidation: RowValidation | undefined) => {
 | 
			
		||||
    //     if (rowValidation) {
 | 
			
		||||
    //       this.eventService.showAbortModal(
 | 
			
		||||
    //         'Excel validation',
 | 
			
		||||
    //         `Please fix the data and re-submit the file. Invalid data details: <br><br> Row: ${rowValidation.rowNumber} <br> Column: ${rowValidation.colName} <br> Reason: <strong>${rowValidation.invalidError}</strong> <br> Invalid value: ${rowValidation.value}`
 | 
			
		||||
    //       )
 | 
			
		||||
 | 
			
		||||
    //       this.excelFileParsing = false
 | 
			
		||||
    //       this.excelUploadState = null
 | 
			
		||||
    //     } else {
 | 
			
		||||
    //       this.excelUploadState = 'Validating-HOT'
 | 
			
		||||
 | 
			
		||||
    //       hot.updateSettings(
 | 
			
		||||
    //         {
 | 
			
		||||
    //           data: this.dataSource
 | 
			
		||||
    //         },
 | 
			
		||||
    //         false
 | 
			
		||||
    //       )
 | 
			
		||||
    //       hot.render()
 | 
			
		||||
 | 
			
		||||
    //       hot.validateCells(() => {
 | 
			
		||||
    //         this.showUploadModal = false
 | 
			
		||||
    //         this.uploadPreview = true
 | 
			
		||||
 | 
			
		||||
    //         this.excelFileParsing = false
 | 
			
		||||
    //         this.excelUploadState = null
 | 
			
		||||
    //       })
 | 
			
		||||
    //     }
 | 
			
		||||
    //   }
 | 
			
		||||
    // )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Drops the attached excel file
 | 
			
		||||
   * @param discardData wheter to discard data parsed from the file or to keep it in the table after dropping a attached excel file
 | 
			
		||||
   */
 | 
			
		||||
  public discardPendingExcel(discardData?: boolean) {
 | 
			
		||||
    this.hotInstance.updateSettings({
 | 
			
		||||
      maxRows: this.licenceState.value.editor_rows_allowed
 | 
			
		||||
@@ -1205,6 +1220,10 @@ export class EditorComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Drops attached excel file, keeps it's data in the DC table
 | 
			
		||||
   * User can now edit the table and submit. Witout the file present.
 | 
			
		||||
   */
 | 
			
		||||
  public previewTableEditConfirm() {
 | 
			
		||||
    this.discardPendingExcel()
 | 
			
		||||
    this.convertToCorrectTypes(this.dataSource)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
import { DcValidation } from 'src/app/shared/dc-validator/models/dc-validation.model'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper for DC Validation because we need `noLinkOption` property
 | 
			
		||||
 * to be used as a flag to show/hide button that generates link for the
 | 
			
		||||
 * edit record modal
 | 
			
		||||
 */
 | 
			
		||||
export interface EditRecordModal extends DcValidation {
 | 
			
		||||
  noLinkOption: boolean
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
export interface CellValidation {
 | 
			
		||||
  data: string
 | 
			
		||||
  length: number
 | 
			
		||||
  type?: string
 | 
			
		||||
  source: string[]
 | 
			
		||||
  format?: number
 | 
			
		||||
  validator?: any
 | 
			
		||||
  valid?: boolean
 | 
			
		||||
  renderer?: any
 | 
			
		||||
  dateFormat?: string
 | 
			
		||||
  readOnly?: boolean
 | 
			
		||||
  desc?: string
 | 
			
		||||
  correctFormat?: boolean
 | 
			
		||||
  /**
 | 
			
		||||
   * Key for accessing object fields, any type because it can be
 | 
			
		||||
   * any of the types interface have
 | 
			
		||||
   */
 | 
			
		||||
  [key: string]: any
 | 
			
		||||
}
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
export enum ColumnType {
 | 
			
		||||
  string = 'string',
 | 
			
		||||
  number = 'number'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ColumnInterface {
 | 
			
		||||
  id: number | undefined
 | 
			
		||||
  name: string | undefined
 | 
			
		||||
  type: ColumnType | undefined
 | 
			
		||||
  length: number | undefined
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Column implements ColumnInterface {
 | 
			
		||||
  public id: number | undefined
 | 
			
		||||
  public name: string | undefined
 | 
			
		||||
  public type: ColumnType | undefined
 | 
			
		||||
  public length: number | undefined
 | 
			
		||||
  public static fromPlainObject(obj: object) {
 | 
			
		||||
    return Object.assign(new Column(), obj)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(id?: number, name?: string, type?: ColumnType, length?: number) {
 | 
			
		||||
    this.id = id
 | 
			
		||||
    this.name = name
 | 
			
		||||
    this.type = type
 | 
			
		||||
    this.length = length
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get hsType() {
 | 
			
		||||
    return (
 | 
			
		||||
      (this.type === ColumnType.string && 'text') ||
 | 
			
		||||
      (this.type === ColumnType.number && 'numeric') ||
 | 
			
		||||
      null
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Model for the dynamic cell validation in the editor
 | 
			
		||||
 * (sending whole row to the backend service and recieving data for the cell dropdown)
 | 
			
		||||
 */
 | 
			
		||||
export interface DynamicExtendedCellValidation {
 | 
			
		||||
  DISPLAY_INDEX: number
 | 
			
		||||
  DISPLAY_TYPE: string
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,14 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Edit record modal - input has been focused event
 | 
			
		||||
 */
 | 
			
		||||
export interface EditRecordInputFocusedEvent {
 | 
			
		||||
  event: any
 | 
			
		||||
  colName: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Edit record modal - dropdown has been changed event
 | 
			
		||||
 */
 | 
			
		||||
export interface EditRecordDropdownChangeEvent {
 | 
			
		||||
  colName: string
 | 
			
		||||
  col: number
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Editor restrictions model (based on the licencing)
 | 
			
		||||
 */
 | 
			
		||||
export interface EditorRestrictions {
 | 
			
		||||
  restrictEditRecord?: boolean // Feature is locked but edit/add record buttons are visible so when user clicks he gets the `locked feature modal`
 | 
			
		||||
  restrictAddRecord?: boolean // Same as editRecord, but for addRecord
 | 
			
		||||
 
 | 
			
		||||
@@ -1,71 +0,0 @@
 | 
			
		||||
import { Column, ColumnType } from './models/column'
 | 
			
		||||
 | 
			
		||||
export enum TableType {
 | 
			
		||||
  INPUT = 'In',
 | 
			
		||||
  OUTPUT = 'Out'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface TableInterface {
 | 
			
		||||
  id: number | undefined
 | 
			
		||||
  name: string | undefined
 | 
			
		||||
  data: Array<Object>
 | 
			
		||||
  columns: Array<Column>
 | 
			
		||||
  type: TableType | undefined
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Table implements TableInterface {
 | 
			
		||||
  public id: number | undefined
 | 
			
		||||
  public name: string | undefined
 | 
			
		||||
  public data: Array<any>
 | 
			
		||||
  public columns: Array<Column> = []
 | 
			
		||||
  public type: TableType | undefined
 | 
			
		||||
 | 
			
		||||
  public static fromPlainObject(obj: any) {
 | 
			
		||||
    obj.columns = obj.columns.map((column: object) => {
 | 
			
		||||
      return Column.fromPlainObject(column)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return Object.assign(new Table(), obj)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    id?: number,
 | 
			
		||||
    name?: string,
 | 
			
		||||
    type?: TableType,
 | 
			
		||||
    data?: Array<Object>,
 | 
			
		||||
    columns?: Array<Column>
 | 
			
		||||
  ) {
 | 
			
		||||
    this.id = id
 | 
			
		||||
    this.name = name
 | 
			
		||||
    this.type = type
 | 
			
		||||
 | 
			
		||||
    this.data = data || [{}]
 | 
			
		||||
    this.columns = columns || []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getNextColumnId(): number {
 | 
			
		||||
    let highestIdColumn: any = this.columns.sort(
 | 
			
		||||
      (cA: any, cB: any) => cA.id - cB.id
 | 
			
		||||
    )[this.columns.length - 1]
 | 
			
		||||
    return (highestIdColumn && highestIdColumn.id + 1) || 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public addColumn(column: Column) {
 | 
			
		||||
    this.columns.push(column)
 | 
			
		||||
 | 
			
		||||
    this.data.forEach((row: any) => {
 | 
			
		||||
      if (column.name) {
 | 
			
		||||
        row[column.name] = column.type === ColumnType.string ? '' : null
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return column
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public removeColumn(colInd: any) {
 | 
			
		||||
    this.data.forEach((row) => {
 | 
			
		||||
      delete row[this.columns[colInd].name!]
 | 
			
		||||
    })
 | 
			
		||||
    this.columns.splice(colInd, 1)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Converting date object to the UTC time string
 | 
			
		||||
 */
 | 
			
		||||
export const dateToUtcTime = (date: Date) => {
 | 
			
		||||
  let timeStr = ('0' + date.getUTCHours()).slice(-2) + ':'
 | 
			
		||||
  timeStr = timeStr + ('0' + date.getUTCMinutes()).slice(-2) + ':'
 | 
			
		||||
@@ -5,6 +8,9 @@ export const dateToUtcTime = (date: Date) => {
 | 
			
		||||
  return timeStr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts date object to the time string
 | 
			
		||||
 */
 | 
			
		||||
export const dateToTime = (date: Date) => {
 | 
			
		||||
  let timeStr = ('0' + date.getHours()).slice(-2) + ':'
 | 
			
		||||
  timeStr = timeStr + ('0' + date.getMinutes()).slice(-2) + ':'
 | 
			
		||||
@@ -12,6 +18,9 @@ export const dateToTime = (date: Date) => {
 | 
			
		||||
  return timeStr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts date object to the YYYY-MM-DD
 | 
			
		||||
 */
 | 
			
		||||
export const dateFormat = (date: Date) => {
 | 
			
		||||
  return (
 | 
			
		||||
    date.getFullYear() +
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,17 @@
 | 
			
		||||
import { Col } from 'src/app/shared/dc-validator/models/col.model'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts excel date serial number to JS date
 | 
			
		||||
 */
 | 
			
		||||
export const excelDateToJSDate = (serial: number) => {
 | 
			
		||||
  return new Date(Math.round((serial - 25569) * 86400 * 1000))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parsing table columns for the HOT in editor
 | 
			
		||||
 * Converts array of objects into array of strings, every string is column name (key)
 | 
			
		||||
 * @param data array of objects (columns data)
 | 
			
		||||
 */
 | 
			
		||||
export const parseTableColumns = (data: Col[]): string[] => {
 | 
			
		||||
  const columns: string[] = []
 | 
			
		||||
 | 
			
		||||
@@ -16,6 +24,12 @@ export const parseTableColumns = (data: Col[]): string[] => {
 | 
			
		||||
  return columns
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Captures headers that are not found in the current table but is found in the uploaded file data
 | 
			
		||||
 * @param data
 | 
			
		||||
 * @param headers
 | 
			
		||||
 * @returns string array of missing headers
 | 
			
		||||
 */
 | 
			
		||||
export const getMissingHeaders = (data: any, headers: any) => {
 | 
			
		||||
  const missingHeaders: string[] = []
 | 
			
		||||
  const remainingHeaders: string[] = []
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Custom renderer for HOT cell
 | 
			
		||||
 * Used to show error icon
 | 
			
		||||
 */
 | 
			
		||||
export const errorRenderer = (
 | 
			
		||||
  instance: any,
 | 
			
		||||
  td: any,
 | 
			
		||||
@@ -14,6 +18,10 @@ export const errorRenderer = (
 | 
			
		||||
  return td
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Custom renderer for HOT cell
 | 
			
		||||
 * Used to revert cell back to original state (no spinner, no error)
 | 
			
		||||
 */
 | 
			
		||||
export const noSpinnerRenderer = (
 | 
			
		||||
  instance: any,
 | 
			
		||||
  td: any,
 | 
			
		||||
@@ -28,7 +36,11 @@ export const noSpinnerRenderer = (
 | 
			
		||||
  return td
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Spinner shown whilst waiting for SAS to respond
 | 
			
		||||
/**
 | 
			
		||||
 * Custom renderer for HOT cell
 | 
			
		||||
 * Used to show loading spinner in the cell
 | 
			
		||||
 * (Spinner shown whilst waiting for SAS to respond)
 | 
			
		||||
 */
 | 
			
		||||
export const spinnerRenderer = (
 | 
			
		||||
  instance: any,
 | 
			
		||||
  td: any,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								client/src/app/licensing/licensing-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								client/src/app/licensing/licensing-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router'
 | 
			
		||||
import { LicensingGuard } from '../routes/licensing.guard'
 | 
			
		||||
import { LicensingComponent } from './licensing.component'
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
  {
 | 
			
		||||
    path: ':action',
 | 
			
		||||
    component: LicensingComponent,
 | 
			
		||||
    canActivate: [LicensingGuard],
 | 
			
		||||
    canDeactivate: [LicensingGuard]
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forChild(routes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class LicensingRoutingModule {}
 | 
			
		||||
							
								
								
									
										20
									
								
								client/src/app/licensing/licensing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								client/src/app/licensing/licensing.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { CommonModule } from '@angular/common'
 | 
			
		||||
 | 
			
		||||
import { LicensingRoutingModule } from './licensing-routing.module'
 | 
			
		||||
import { ClarityModule } from '@clr/angular'
 | 
			
		||||
import { SharedModule } from '../shared/shared.module'
 | 
			
		||||
import { LicensingComponent } from './licensing.component'
 | 
			
		||||
import { FormsModule } from '@angular/forms'
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [LicensingComponent],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    FormsModule,
 | 
			
		||||
    ClarityModule,
 | 
			
		||||
    LicensingRoutingModule,
 | 
			
		||||
    SharedModule
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class LicensingModule {}
 | 
			
		||||
							
								
								
									
										5
									
								
								client/src/app/models/ErrorBody.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								client/src/app/models/ErrorBody.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
export interface ErrorBody {
 | 
			
		||||
  message: string
 | 
			
		||||
  details: any
 | 
			
		||||
  raw: any
 | 
			
		||||
}
 | 
			
		||||
@@ -137,6 +137,11 @@ export class QueryComponent
 | 
			
		||||
  public whereClause: string | undefined
 | 
			
		||||
  public logicOperators: Array<string> = ['AND', 'OR']
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Temporary values array used in pickers
 | 
			
		||||
   * because they need particular format to work
 | 
			
		||||
   * before sending values to backend, values are parsed
 | 
			
		||||
   */
 | 
			
		||||
  public queryDateTime: QueryDateTime[] = []
 | 
			
		||||
 | 
			
		||||
  public currentClauseIndex: number = -1
 | 
			
		||||
@@ -158,6 +163,11 @@ export class QueryComponent
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets and sets temporary values selected with DATETIME or TIME picker
 | 
			
		||||
   * Those values are used for picker to work with format it lieks
 | 
			
		||||
   * Later before sending values to backend, values are parsed
 | 
			
		||||
   */
 | 
			
		||||
  getQueryDateTime(clauseIndex: number, queryIndex: number): QueryDateTime {
 | 
			
		||||
    let existingQueryDateTime = this.queryDateTime.find(
 | 
			
		||||
      (x) => x.clauseIndex === clauseIndex && x.queryIndex === queryIndex
 | 
			
		||||
@@ -178,10 +188,16 @@ export class QueryComponent
 | 
			
		||||
    return existingQueryDateTime
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * When toggling pickers feature we reset the temp picker values array
 | 
			
		||||
   */
 | 
			
		||||
  usePickersChange() {
 | 
			
		||||
    this.queryDateTime = []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resets all variables used for filtering
 | 
			
		||||
   */
 | 
			
		||||
  public resetFilter() {
 | 
			
		||||
    this.whereString = undefined
 | 
			
		||||
    this.whereClause = undefined
 | 
			
		||||
@@ -210,6 +226,10 @@ export class QueryComponent
 | 
			
		||||
    this.whereClauseFn(true)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * `Globals` are used to store filtering state (variables) as a caching feature
 | 
			
		||||
   * until browser reloads
 | 
			
		||||
   */
 | 
			
		||||
  public setToGlobals() {
 | 
			
		||||
    if (!this.caching) return
 | 
			
		||||
 | 
			
		||||
@@ -237,6 +257,10 @@ export class QueryComponent
 | 
			
		||||
    console.log('globals', globals)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * `Globals` are used to store filtering state (variables) as a caching feature
 | 
			
		||||
   * until browser reloads
 | 
			
		||||
   */
 | 
			
		||||
  public getFromGlobals() {
 | 
			
		||||
    if (!this.caching) return
 | 
			
		||||
 | 
			
		||||
@@ -269,6 +293,11 @@ export class QueryComponent
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets filtering multiple caluses group logic (and / or)
 | 
			
		||||
   *
 | 
			
		||||
   * @param groupLogic to set
 | 
			
		||||
   */
 | 
			
		||||
  public setGroupLogic(groupLogic: any) {
 | 
			
		||||
    this.groupLogic = groupLogic
 | 
			
		||||
    this.clauses.groupLogic = groupLogic
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
import { ActivatedRoute } from '@angular/router'
 | 
			
		||||
import { SasStoreService } from '../services/sas-store.service'
 | 
			
		||||
import { SasStoreService } from '../../services/sas-store.service'
 | 
			
		||||
import { Component, AfterViewInit, OnDestroy } from '@angular/core'
 | 
			
		||||
import { Subscription } from 'rxjs'
 | 
			
		||||
import { Router } from '@angular/router'
 | 
			
		||||
import { EventService } from '../services/event.service'
 | 
			
		||||
import { EventService } from '../../services/event.service'
 | 
			
		||||
import {
 | 
			
		||||
  AuditorsPostdataSASResponse,
 | 
			
		||||
  Param
 | 
			
		||||
} from '../models/sas/auditors-postdata.model'
 | 
			
		||||
} from '../../models/sas/auditors-postdata.model'
 | 
			
		||||
 | 
			
		||||
interface ChangesObj {
 | 
			
		||||
  ind: any
 | 
			
		||||
@@ -89,7 +89,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public goToApprovalsList() {
 | 
			
		||||
    this.route.navigateByUrl('/approve')
 | 
			
		||||
    this.route.navigateByUrl('/review/approve')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getTable(tableId: any) {
 | 
			
		||||
@@ -136,7 +136,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
 | 
			
		||||
    await this.sasStoreService
 | 
			
		||||
      .rejecting(rejParams, 'BrowserParams', 'approvers/rejection')
 | 
			
		||||
      .then((res: any) => {
 | 
			
		||||
        this.route.navigateByUrl('/history')
 | 
			
		||||
        this.route.navigateByUrl('/review/history')
 | 
			
		||||
      })
 | 
			
		||||
      .catch((err: any) => {
 | 
			
		||||
        this.acceptLoading = false
 | 
			
		||||
@@ -156,7 +156,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
 | 
			
		||||
    await this.sasStoreService
 | 
			
		||||
      .approveTable(approveParams, 'SASControlTable', 'auditors/postdata')
 | 
			
		||||
      .then((res: any) => {
 | 
			
		||||
        this.route.navigateByUrl('/history')
 | 
			
		||||
        this.route.navigateByUrl('/review/history')
 | 
			
		||||
      })
 | 
			
		||||
      .catch((err: any) => {
 | 
			
		||||
        this.acceptLoading = false
 | 
			
		||||
@@ -164,7 +164,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public goToSubmitList() {
 | 
			
		||||
    this.route.navigateByUrl('/submitted')
 | 
			
		||||
    this.route.navigateByUrl('/review/submitted')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async callChangesInfo(tableId: any) {
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
import { Component, OnInit, ChangeDetectorRef } from '@angular/core'
 | 
			
		||||
import { SasStoreService } from '../services/sas-store.service'
 | 
			
		||||
import { SasStoreService } from '../../services/sas-store.service'
 | 
			
		||||
import { Router } from '@angular/router'
 | 
			
		||||
import { SasService } from '../services/sas.service'
 | 
			
		||||
import { EventService } from '../services/event.service'
 | 
			
		||||
import { SasService } from '../../services/sas.service'
 | 
			
		||||
import { EventService } from '../../services/event.service'
 | 
			
		||||
 | 
			
		||||
interface ApproveData {
 | 
			
		||||
  tableId: string
 | 
			
		||||
@@ -45,7 +45,7 @@ export class ApproveComponent implements OnInit {
 | 
			
		||||
    if (this.approveList !== undefined) {
 | 
			
		||||
      this.tableId = this.approveList[ind].tableId
 | 
			
		||||
      this.route.navigateByUrl(
 | 
			
		||||
        'approve/approveDet/' + this.approveList[ind].tableId
 | 
			
		||||
        'review/approveDet/' + this.approveList[ind].tableId
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core'
 | 
			
		||||
 | 
			
		||||
import { SasStoreService } from '../services/sas-store.service'
 | 
			
		||||
import { Router } from '@angular/router'
 | 
			
		||||
import { SasService } from '../services/sas.service'
 | 
			
		||||
import { EventService } from '../services/event.service'
 | 
			
		||||
import { SASjsConfig } from '@sasjs/adapter'
 | 
			
		||||
import { LicenceService } from '../services/licence.service'
 | 
			
		||||
import {
 | 
			
		||||
  LicenceService,
 | 
			
		||||
  SasStoreService,
 | 
			
		||||
  EventService,
 | 
			
		||||
  SasService
 | 
			
		||||
} from 'src/app/services'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-history',
 | 
			
		||||
							
								
								
									
										22
									
								
								client/src/app/review/review-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								client/src/app/review/review-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
import { CommonModule } from '@angular/common'
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router'
 | 
			
		||||
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
 | 
			
		||||
import { ApproveComponent } from './approve/approve.component'
 | 
			
		||||
import { SubmitterComponent } from './submitter/submitter.component'
 | 
			
		||||
import { HistoryComponent } from './history/history.component'
 | 
			
		||||
 | 
			
		||||
const ROUTES: Routes = [
 | 
			
		||||
  { path: 'approve', component: ApproveComponent },
 | 
			
		||||
  { path: 'approveDet/:tableId', component: ApproveDetailsComponent },
 | 
			
		||||
  { path: 'submitted', component: SubmitterComponent },
 | 
			
		||||
  { path: 'submitted/:tableId', component: SubmitterComponent },
 | 
			
		||||
  { path: 'history', component: HistoryComponent }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [],
 | 
			
		||||
  imports: [CommonModule, RouterModule.forChild(ROUTES)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class ReviewRoutingModule {}
 | 
			
		||||
							
								
								
									
										31
									
								
								client/src/app/review/review.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								client/src/app/review/review.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
import { CommonModule } from '@angular/common'
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { FormsModule } from '@angular/forms'
 | 
			
		||||
import { ClarityModule } from '@clr/angular'
 | 
			
		||||
import { HotTableModule } from '@handsontable/angular'
 | 
			
		||||
import { DirectivesModule } from '../directives/directives.module'
 | 
			
		||||
import { SharedModule } from '../shared/shared.module'
 | 
			
		||||
import { ApproveDetailsComponent } from './approve-details/approve-details.component'
 | 
			
		||||
import { ApproveComponent } from './approve/approve.component'
 | 
			
		||||
import { ReviewRoutingModule } from './review-routing.module'
 | 
			
		||||
import { SubmitterComponent } from './submitter/submitter.component'
 | 
			
		||||
import { HistoryComponent } from './history/history.component'
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    ApproveComponent,
 | 
			
		||||
    ApproveDetailsComponent,
 | 
			
		||||
    SubmitterComponent,
 | 
			
		||||
    HistoryComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    FormsModule,
 | 
			
		||||
    ReviewRoutingModule,
 | 
			
		||||
    ClarityModule,
 | 
			
		||||
    HotTableModule.forRoot(),
 | 
			
		||||
    DirectivesModule,
 | 
			
		||||
    SharedModule
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class ReviewModule {}
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
import { Component, AfterViewInit, OnInit } from '@angular/core'
 | 
			
		||||
import { Subscription } from 'rxjs'
 | 
			
		||||
import { SasStoreService } from '../services/sas-store.service'
 | 
			
		||||
import { ActivatedRoute, Router } from '@angular/router'
 | 
			
		||||
import { SasService } from '../services/sas.service'
 | 
			
		||||
import { EventService } from '../services/event.service'
 | 
			
		||||
import { SasStoreService, EventService, SasService } from '../../services'
 | 
			
		||||
 | 
			
		||||
interface SubmitterData {
 | 
			
		||||
  tableId: string
 | 
			
		||||
@@ -46,7 +44,7 @@ export class SubmitterComponent implements OnInit, AfterViewInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public goToDetails(table_id: any) {
 | 
			
		||||
    this.router.navigateByUrl('/submitted/' + table_id)
 | 
			
		||||
    this.router.navigateByUrl('/review/submitted/' + table_id)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getDetails(sub: any, index: any) {
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-approve-route',
 | 
			
		||||
  templateUrl: './approve-route.component.html',
 | 
			
		||||
  styleUrls: ['./approve-route.component.scss'],
 | 
			
		||||
  host: {
 | 
			
		||||
    class: 'content-container'
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
export class ApproveRouteComponent implements OnInit {
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {}
 | 
			
		||||
}
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
<router-outlet></router-outlet>
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-edit-route',
 | 
			
		||||
  templateUrl: './edit-route.component.html',
 | 
			
		||||
  styleUrls: ['./edit-route.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class EditRouteComponent implements OnInit {
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {}
 | 
			
		||||
}
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
<router-outlet></router-outlet>
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-history-route',
 | 
			
		||||
  templateUrl: './history-route.component.html',
 | 
			
		||||
  styleUrls: ['./history-route.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class HistoryRouteComponent implements OnInit {
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								client/src/app/routes/review-route/review-route.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								client/src/app/routes/review-route/review-route.component.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core'
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-review-route',
 | 
			
		||||
  templateUrl: './review-route.component.html',
 | 
			
		||||
  styleUrls: ['./review-route.component.scss'],
 | 
			
		||||
  host: {
 | 
			
		||||
    class: 'content-container'
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
export class ReviewRouteComponent implements OnInit {
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {}
 | 
			
		||||
}
 | 
			
		||||
@@ -17,6 +17,17 @@ export class HelperService {
 | 
			
		||||
    console.log('Is IE or Edge?', this.isMicrosoft)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Converts a JavaScript date object to a SAS Date or Datetime, given the logic below:
 | 
			
		||||
   *
 | 
			
		||||
   * A JS Date contains the number of _milliseconds_ since 01/01/1970
 | 
			
		||||
   * A SAS Date contains the number of _days_ since 01/01/1960
 | 
			
		||||
   * A SAS Datetime contains the number of _seconds_ since 01/01/1960
 | 
			
		||||
   *
 | 
			
		||||
   * @param jsDate JS Date to be converted. The type is instance of `Date`
 | 
			
		||||
   * @param unit Unit in which to return the SAS Date / datetime, eg `sasdate | sasdatetime`
 | 
			
		||||
   * @returns SAS Date value based on `unit` param
 | 
			
		||||
   */
 | 
			
		||||
  public convertJsDateToSasDate(
 | 
			
		||||
    jsDate: string | Date,
 | 
			
		||||
    unit: string = 'days'
 | 
			
		||||
@@ -63,6 +74,17 @@ export class HelperService {
 | 
			
		||||
    return 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Converts a SAS Date or Datetime to a JavaScript date object, given the logic below:
 | 
			
		||||
   *
 | 
			
		||||
   * A JS Date contains the number of _milliseconds_ since 01/01/1970
 | 
			
		||||
   * A SAS Date contains the number of _days_ since 01/01/1960
 | 
			
		||||
   * A SAS Datetime contains the number of _seconds_ since 01/01/1960
 | 
			
		||||
   *
 | 
			
		||||
   * @param sasValue SAS Date or Datetime to be converted. The type could be `number` or `string.
 | 
			
		||||
   * @param unit Unit from which to convert the SAS Date / Datetime, eg `sasdate | sasdatetime`
 | 
			
		||||
   * @returns JavaScript Date object
 | 
			
		||||
   */
 | 
			
		||||
  public convertSasDaysToJsDate(
 | 
			
		||||
    sasValue: number | string,
 | 
			
		||||
    unit: string = 'days'
 | 
			
		||||
@@ -87,6 +109,11 @@ export class HelperService {
 | 
			
		||||
    return new Date(msNegativeTenYears + sasValue * msInDay)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param array all elements in the clarity tree
 | 
			
		||||
   * @param arrToFilter sub array in the tree to be filtered for example `tables`
 | 
			
		||||
   */
 | 
			
		||||
  public treeOnFilter(array: any, arrToFilter: string) {
 | 
			
		||||
    let search = array['searchString'] ? array['searchString'] : ''
 | 
			
		||||
    let arrToFilterArray = arrToFilter.split('.')[0]
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,16 @@ export class SasStoreService {
 | 
			
		||||
    private loggerService: LoggerService
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Wrapper for making request to service
 | 
			
		||||
   * Should be removed, as it's redundant now
 | 
			
		||||
   * TODO: Refactor to call editors/getdata directly
 | 
			
		||||
   * @param tableData
 | 
			
		||||
   * @param tableName
 | 
			
		||||
   * @param program
 | 
			
		||||
   * @param libds
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public async callService(
 | 
			
		||||
    tableData: Array<any>,
 | 
			
		||||
    tableName: string,
 | 
			
		||||
@@ -60,6 +70,15 @@ export class SasStoreService {
 | 
			
		||||
    return response
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Calling editors/stagedata - saving table data, sending request to backend
 | 
			
		||||
   * @param tableParams params to send to backend
 | 
			
		||||
   * @param tableData data to be updated
 | 
			
		||||
   * @param tableName name of the table to be updated
 | 
			
		||||
   * @param program service against which we send request
 | 
			
		||||
   * @param $dataFormats column data formats recieved from backend, sending it back
 | 
			
		||||
   * @returns adapter.request() response
 | 
			
		||||
   */
 | 
			
		||||
  public async updateTable(
 | 
			
		||||
    tableParams: any,
 | 
			
		||||
    tableData: any,
 | 
			
		||||
@@ -86,6 +105,13 @@ export class SasStoreService {
 | 
			
		||||
    return res
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sending request to 'approvers/getapprovals' to fetch approvals list
 | 
			
		||||
   * @param tableData sending to backend table data
 | 
			
		||||
   * @param tableName sending to backend table name
 | 
			
		||||
   * @param program service to run request on
 | 
			
		||||
   * @returns HTTP Response
 | 
			
		||||
   */
 | 
			
		||||
  public async getApprovals(
 | 
			
		||||
    tableData: any,
 | 
			
		||||
    tableName: string,
 | 
			
		||||
@@ -96,6 +122,13 @@ export class SasStoreService {
 | 
			
		||||
    let res: any = await this.sasService.request(program, tables)
 | 
			
		||||
    return res
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Interceptor for loading of the submitted details
 | 
			
		||||
   * @param detail submitter
 | 
			
		||||
   * @param index submitter index
 | 
			
		||||
   * @param data submit data
 | 
			
		||||
   */
 | 
			
		||||
  public async sendDetails(detail: any, index: any, data: any) {
 | 
			
		||||
    let details = Object.assign({ sub: true }, detail)
 | 
			
		||||
    let subData = data[index]
 | 
			
		||||
@@ -105,11 +138,20 @@ export class SasStoreService {
 | 
			
		||||
    }
 | 
			
		||||
    this.submittDetail.next(allData)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @returns All submits
 | 
			
		||||
   */
 | 
			
		||||
  public async getSubmitts() {
 | 
			
		||||
    let res: any = await this.sasService.request('editors/getsubmits', null)
 | 
			
		||||
    return res
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @returns All libraries
 | 
			
		||||
   */
 | 
			
		||||
  public async viewLibs() {
 | 
			
		||||
    return this.sasService.request('public/viewlibs', null)
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import { DcAdapterSettings } from '../models/DcAdapterSettings'
 | 
			
		||||
import { AppStoreService } from './app-store.service'
 | 
			
		||||
import { LoggerService } from './logger.service'
 | 
			
		||||
import { RequestWrapperOptions } from '../models/RequestWrapperOptions'
 | 
			
		||||
import { ErrorBody } from '../models/ErrorBody'
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
@@ -39,6 +40,11 @@ export class SasService {
 | 
			
		||||
    private router: Router
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Same as `setup` function in the sasjs.service, this is the constructor replacement.
 | 
			
		||||
   * This function is being called by `app.service`.
 | 
			
		||||
   * Because of timing and dependency issues
 | 
			
		||||
   */
 | 
			
		||||
  public sasServiceInit() {
 | 
			
		||||
    this.dcAdapterSettings = this.appStoreService.getDcAdapterSettings()
 | 
			
		||||
 | 
			
		||||
@@ -80,6 +86,16 @@ export class SasService {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Runing a backend request against a service.
 | 
			
		||||
   * Function also handles the displaying of success or error modals.
 | 
			
		||||
   *
 | 
			
		||||
   * @param url service to run reuqest against
 | 
			
		||||
   * @param data to be sent to backend service
 | 
			
		||||
   * @param config additional parameters to force eg. { debug: false }
 | 
			
		||||
   * @param wrapperOptions used to suppress error or success abort modals after request is finished
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public request(
 | 
			
		||||
    url: string,
 | 
			
		||||
    data: any,
 | 
			
		||||
@@ -197,6 +213,14 @@ export class SasService {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Uploads a file to the backend, using the adapter upload function.
 | 
			
		||||
   *
 | 
			
		||||
   * @param sasService Service to which the file will be sent
 | 
			
		||||
   * @param files Files to be sent
 | 
			
		||||
   * @param params Aditional parameters eg. { debug: false }
 | 
			
		||||
   * @returns HTTP Response
 | 
			
		||||
   */
 | 
			
		||||
  public uploadFile(sasService: string, files: UploadFile[], params: any) {
 | 
			
		||||
    return this.sasjsAdapter.uploadFile(sasService, files, params)
 | 
			
		||||
  }
 | 
			
		||||
@@ -487,9 +511,3 @@ export class SasService {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface ErrorBody {
 | 
			
		||||
  message: string
 | 
			
		||||
  details: any
 | 
			
		||||
  raw: any
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,12 @@ export class SasjsService {
 | 
			
		||||
    private appStoreService: AppStoreService
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * This function is replacing the constructor.
 | 
			
		||||
   * The reason for this is timing issues, other services eg. sas.service, app-store.service
 | 
			
		||||
   * must be initialized before this bit of code is executed.
 | 
			
		||||
   * This function is being called by `sas.service`
 | 
			
		||||
   */
 | 
			
		||||
  setup() {
 | 
			
		||||
    const adapterConfig = this.appStoreService.getDcAdapterSettings()
 | 
			
		||||
 | 
			
		||||
@@ -32,10 +38,18 @@ export class SasjsService {
 | 
			
		||||
    this.driveUrl = `${this.url}/drive`
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @returns Sasjs/server information
 | 
			
		||||
   */
 | 
			
		||||
  getServerInfo(): Observable<SASjsApiServerInfo> {
 | 
			
		||||
    return this.http.get<SASjsApiServerInfo>(`${this.url}/info`)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets file contents on a given path
 | 
			
		||||
   * @param filePath path to the file
 | 
			
		||||
   */
 | 
			
		||||
  getFileFromDrive(filePath: string) {
 | 
			
		||||
    return this.http.get(
 | 
			
		||||
      `${this.driveUrl}/file/?_filePath=${filePath}`,
 | 
			
		||||
@@ -43,6 +57,11 @@ export class SasjsService {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets folder contents on a given path
 | 
			
		||||
   * @param folderPath path to the folder
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  getFolderContentsFromDrive(
 | 
			
		||||
    folderPath: string
 | 
			
		||||
  ): Observable<SASjsApiDriveFolderContents> {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,14 @@ export class InfoModalComponent implements OnInit {
 | 
			
		||||
    this.data = newData
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Wheter or not to show the `Open configurator button`
 | 
			
		||||
   * Button used for navigating to the `configuration` page
 | 
			
		||||
   * Only for SAS9
 | 
			
		||||
   * @param sasService backend service that caused this info modal to be shown
 | 
			
		||||
   * Decision is made based on that service path
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  showConfiguratorButton(sasService: string | null) {
 | 
			
		||||
    const sasjsConfig = this.sasService.getSasjsConfig()
 | 
			
		||||
 | 
			
		||||
@@ -54,6 +62,9 @@ export class InfoModalComponent implements OnInit {
 | 
			
		||||
    this.onConfirmModalClick.emit()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Only on SAS9, opening a backend configurator/deploy page
 | 
			
		||||
   */
 | 
			
		||||
  openConfigurator() {
 | 
			
		||||
    this.eventService.startupDataLoaded()
 | 
			
		||||
    this.router.navigateByUrl('/deploy')
 | 
			
		||||
 
 | 
			
		||||
@@ -55,14 +55,14 @@
 | 
			
		||||
        <a
 | 
			
		||||
          *ngIf="isMainRoute('approve')"
 | 
			
		||||
          clrVerticalNavLink
 | 
			
		||||
          routerLink="/approve/submitted"
 | 
			
		||||
          routerLink="/review/approve/submitted"
 | 
			
		||||
          routerLinkActive="active"
 | 
			
		||||
          >Submitted</a
 | 
			
		||||
        >
 | 
			
		||||
        <a
 | 
			
		||||
          *ngIf="isMainRoute('approve')"
 | 
			
		||||
          clrVerticalNavLink
 | 
			
		||||
          routerLink="/approve/toapprove"
 | 
			
		||||
          routerLink="/review/approve/toapprove"
 | 
			
		||||
          routerLinkActive="active"
 | 
			
		||||
          >To Approve</a
 | 
			
		||||
        >
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ export class StageComponent implements OnInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public approveTableScreen() {
 | 
			
		||||
    this.route.navigateByUrl('/approve/approveDet/' + this.table_id)
 | 
			
		||||
    this.route.navigateByUrl('/review/approveDet/' + this.table_id)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public viewerTableScreen() {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								client/src/app/system/system-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								client/src/app/system/system-routing.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router'
 | 
			
		||||
import { SystemComponent } from './system.component'
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [{ path: '', component: SystemComponent }]
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forChild(routes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class SystemRoutingModule {}
 | 
			
		||||
							
								
								
									
										12
									
								
								client/src/app/system/system.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								client/src/app/system/system.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
import { NgModule } from '@angular/core'
 | 
			
		||||
import { CommonModule } from '@angular/common'
 | 
			
		||||
 | 
			
		||||
import { SystemRoutingModule } from './system-routing.module'
 | 
			
		||||
import { SystemComponent } from './system.component'
 | 
			
		||||
import { ClarityModule } from '@clr/angular'
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [SystemComponent],
 | 
			
		||||
  imports: [CommonModule, SystemRoutingModule, ClarityModule]
 | 
			
		||||
})
 | 
			
		||||
export class SystemModule {}
 | 
			
		||||
@@ -201,16 +201,28 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Open viewboxes modal
 | 
			
		||||
   */
 | 
			
		||||
  public newViewbox() {
 | 
			
		||||
    this.viewboxOpen = true
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Resetting filter variables
 | 
			
		||||
   */
 | 
			
		||||
  public resetFilter() {
 | 
			
		||||
    if (this.queryFilterCompList.first) {
 | 
			
		||||
      this.queryFilterCompList.first.resetFilter()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Searching table against particular string, data is comming from backend.
 | 
			
		||||
   * There is also a toggle that will search for a numeric values
 | 
			
		||||
   *
 | 
			
		||||
   * @param inputElement input from which search string is captured
 | 
			
		||||
   */
 | 
			
		||||
  public async searchTable(inputElement: any) {
 | 
			
		||||
    this.searchLoading = true
 | 
			
		||||
 | 
			
		||||
@@ -249,6 +261,9 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    this.searchLoading = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Re sending request to backend and re-setting data in the HOT
 | 
			
		||||
   */
 | 
			
		||||
  public reloadTableData() {
 | 
			
		||||
    this.viewData(this.urlFilterPk || 0)
 | 
			
		||||
  }
 | 
			
		||||
@@ -278,6 +293,9 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * FIXME: Should be removed, not used
 | 
			
		||||
   */
 | 
			
		||||
  public filterFn(input: string) {
 | 
			
		||||
    let libraries = this.libraries
 | 
			
		||||
    this.libraries = libraries.filter(
 | 
			
		||||
@@ -286,6 +304,9 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Downloads file from backend, against `getrawdata` service, link is created and open in new tab
 | 
			
		||||
   */
 | 
			
		||||
  public downloadData() {
 | 
			
		||||
    let storage = this.sasjsConfig.serverUrl
 | 
			
		||||
    let metaData = this.sasjsConfig.appLoc
 | 
			
		||||
@@ -320,6 +341,9 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    this.openDownload = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Downloads file from backend, against `getddl` service, link is created and open in new tab
 | 
			
		||||
   */
 | 
			
		||||
  public downloadDDL() {
 | 
			
		||||
    let libref = this.lib
 | 
			
		||||
    let ds = this.table
 | 
			
		||||
@@ -346,15 +370,27 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    this.openDownload = false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * When clicked on textarea in the Web Query Modal, this function will
 | 
			
		||||
   * select all text inside.
 | 
			
		||||
   * @param evt textarea which contains the web query text
 | 
			
		||||
   */
 | 
			
		||||
  public onCliCommandFocus(evt: any): void {
 | 
			
		||||
    evt.preventDefault()
 | 
			
		||||
    evt.target.select()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Navigate to the edit page of a viewing table
 | 
			
		||||
   */
 | 
			
		||||
  public editTable() {
 | 
			
		||||
    this.router.navigateByUrl('/editor/' + this.libTab)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Used to show/hide the edit table button
 | 
			
		||||
   * @returns Wheter currently viewed table is edtiable
 | 
			
		||||
   */
 | 
			
		||||
  public tableEditExists() {
 | 
			
		||||
    let editTables: any = {}
 | 
			
		||||
    editTables = globals.editor.libsAndTables
 | 
			
		||||
@@ -367,12 +403,18 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
 | 
			
		||||
    return editTables[currentLibrary].includes(currentTable)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Navigate to the lineage of a viewing table
 | 
			
		||||
   */
 | 
			
		||||
  public goToLineage() {
 | 
			
		||||
    let routeUri = this.tableuri!.split('\\')[1]
 | 
			
		||||
    let lineageUrl = `/view/lineage/${routeUri}/REVERSE`
 | 
			
		||||
    this.router.navigateByUrl(lineageUrl)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Displays web query modal
 | 
			
		||||
   */
 | 
			
		||||
  public showWebQuery() {
 | 
			
		||||
    this.webQuery = true
 | 
			
		||||
    let filter_pk: number
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,22 @@ import { SharedModule } from '../shared/shared.module'
 | 
			
		||||
import { ViewboxesModule } from '../shared/viewboxes/viewboxes.module'
 | 
			
		||||
import { QueryModule } from '../query/query.module'
 | 
			
		||||
import { DirectivesModule } from '../directives/directives.module'
 | 
			
		||||
import { UserComponent } from '../user/user.component'
 | 
			
		||||
import { RoleComponent } from '../role/role.component'
 | 
			
		||||
import { GroupComponent } from '../group/group.component'
 | 
			
		||||
import { LineageComponent } from '../lineage/lineage.component'
 | 
			
		||||
import { MetadataComponent } from '../metadata/metadata.component'
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [ViewerComponent, ViewRouteComponent],
 | 
			
		||||
  declarations: [
 | 
			
		||||
    ViewerComponent,
 | 
			
		||||
    ViewRouteComponent,
 | 
			
		||||
    UserComponent,
 | 
			
		||||
    RoleComponent,
 | 
			
		||||
    GroupComponent,
 | 
			
		||||
    LineageComponent,
 | 
			
		||||
    MetadataComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    ViewboxesModule,
 | 
			
		||||
    CommonModule,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								client/tsconfig.doc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								client/tsconfig.doc.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{"include":["src/**/*.ts"],"exclude":["src/**/*.spec.ts"]}
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "out": "../tsdoc",
 | 
			
		||||
  "tsconfig": "./tsconfig.app.json",
 | 
			
		||||
  "entryPointStrategy": "expand",
 | 
			
		||||
  "entryPoints": [
 | 
			
		||||
    "./src"
 | 
			
		||||
  ],
 | 
			
		||||
  "exclude": "**/*+(index|.spec|.e2e).ts",
 | 
			
		||||
  "externalPattern": "**/node_modules/**",
 | 
			
		||||
  "excludeExternals": true,
 | 
			
		||||
  "excludePrivate": true
 | 
			
		||||
}
 | 
			
		||||
@@ -283,7 +283,7 @@
 | 
			
		||||
        "rejectUnauthorized": false,
 | 
			
		||||
        "allowInsecureRequests": true
 | 
			
		||||
      },
 | 
			
		||||
      "appLoc": "/Public/app/mihajlo",
 | 
			
		||||
      "appLoc": "/Public/app/dc2",
 | 
			
		||||
      "deployConfig": {
 | 
			
		||||
        "deployServicePack": true,
 | 
			
		||||
        "deployScripts": []
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user