From 3b065655523a4f74612b03d0dd2ed303665295c7 Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Tue, 14 Apr 2020 13:09:47 +0200
Subject: [PATCH] chore: added user doc chore: auto gen images

---
 common/constants.js                           | 11 ++++
 docs/.gitignore                               |  1 +
 docs/Dockerfile                               | 26 ++++++++
 docs/releases/v2.2.0.md                       |  5 ++
 docs/usage/sharing.md                         | 24 ++++++++
 e2e/screenshots/gen.js                        | 25 ++++++++
 e2e/src/selecting/share.e2e-screenshot.js     | 61 +++++++++++++++++++
 e2e/src/util.js                               | 30 +++++++++
 mkdocs.yml                                    |  2 +
 package.json                                  |  1 +
 .../statusCard/statusCard.component.ts        | 13 +++-
 .../statusCard/statusCard.template.html       |  9 ++-
 12 files changed, 204 insertions(+), 4 deletions(-)
 create mode 100644 common/constants.js
 create mode 100644 docs/.gitignore
 create mode 100644 docs/releases/v2.2.0.md
 create mode 100644 docs/usage/sharing.md
 create mode 100644 e2e/screenshots/gen.js
 create mode 100644 e2e/src/selecting/share.e2e-screenshot.js

diff --git a/common/constants.js b/common/constants.js
new file mode 100644
index 000000000..363efa6a8
--- /dev/null
+++ b/common/constants.js
@@ -0,0 +1,11 @@
+(function(exports){
+
+  exports.ARIA_LABELS = {
+
+    // sharing module
+    SHARE_BTN: `Share this view`,
+    SHARE_COPY_URL_CLIPBOARD: `Copy URL to clipboard`,
+    SHARE_CUSTOM_URL: 'Create a custom URL',
+    SHARE_CUSTOM_URL_DIALOG: 'Dialog for creating a custom URL'
+  }
+})(typeof exports === 'undefined' ? module.exports : exports)
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 000000000..ceb8b070b
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+autogen_images
diff --git a/docs/Dockerfile b/docs/Dockerfile
index 668554115..b017c579c 100644
--- a/docs/Dockerfile
+++ b/docs/Dockerfile
@@ -1,9 +1,35 @@
+# TODO using dockerfile will not work for readthedocs ... 
+# need to consider how to build for read the docs
+
+FROM node:12 as img_autogen
+
+COPY . /iav
+WORKDIR /iav
+
+# build aot first && install webdriver & pptr
+# parallel build-aot, update webdriver and install pptr
+RUN npm i && \
+    npm run build-aot & \
+    npm run wd -- update --versions.chrome=80.0.3987.106 & \
+    npm i --no-save puppeteer@2.1.0
+
+# install deploy folder
+RUN cd deploy && \
+    npm i
+
+# auto generate screenshots
+RUN npm run e2e -- --specs ./e2e/screenshots/gen.js
+
+
 FROM python:3.7 as builder
 
 COPY . /iav
 WORKDIR /iav
 
 RUN pip install mkdocs mkdocs-material mdx_truly_sane_lists
+
+COPY --from=img_autogen /iav/docs/autogen_images /iav/docs/autogen_images
+
 RUN mkdocs build
 
 FROM nginx:alpine
diff --git a/docs/releases/v2.2.0.md b/docs/releases/v2.2.0.md
new file mode 100644
index 000000000..3db6c411e
--- /dev/null
+++ b/docs/releases/v2.2.0.md
@@ -0,0 +1,5 @@
+# v2.2.0
+
+## New features:
+
+- [sane url sharing](../usage/sharing.md)
\ No newline at end of file
diff --git a/docs/usage/sharing.md b/docs/usage/sharing.md
new file mode 100644
index 000000000..ba0046c6f
--- /dev/null
+++ b/docs/usage/sharing.md
@@ -0,0 +1,24 @@
+# Sharing
+
+Most of the viewer state are [saved in the URL](../advanced/url.md). Therefore, bookmarking / sending URL is a good way of saving / sharing a view of interest. Users may also generate a more human readable URL.
+
+A share button has been added in [v2.2.0](../releases/v2.2.0.md) to simplify this process.
+
+[![](../autogen_images/share_highlightShareBtn.png)](../autogen_images/share_highlightShareBtn.png)
+
+## Share URL
+
+`Share link to this view` will attempt to copy the current URL to the clipboard. It can then be sent or saved to restore the current view.
+
+[![](../autogen_images/share_highlightShareURL.png)](../autogen_images/share_highlightShareURL.png)
+
+## Create custom URL
+
+`Create custom URL` will allow users to create a more human readable URL. 
+
+!!! warning
+    Links generated by unauthenticated users will expire after 72 hours.
+
+[![](../autogen_images/share_highlightShareURL.png)](../autogen_images/share_highlightShareURL.png)
+
+[![](../autogen_images/share_shareCustomURLDialog.png)](../autogen_images/share_shareCustomURLDialog.png)
diff --git a/e2e/screenshots/gen.js b/e2e/screenshots/gen.js
new file mode 100644
index 000000000..d81a922c7
--- /dev/null
+++ b/e2e/screenshots/gen.js
@@ -0,0 +1,25 @@
+const { spawn } = require("child_process")
+const path = require('path')
+const glob = require('glob')
+describe('> generating screenshot', () => {
+  let childProcess
+  beforeAll(done => {
+    const cwdPath = path.join(__dirname, '../../deploy/')
+    childProcess = spawn('node', ['server.js'],  {
+      cwd: cwdPath
+    })
+    setTimeout(done, 1000)
+  })
+
+  require('../src/selecting/share.e2e-screenshot')
+  glob('../src/**/*.e2e-screenshot.js', (err, matches) => {
+    if (err) throw err
+    for (const match of matches) {
+      require(match)
+    }
+  })
+
+  afterAll(() => {
+    childProcess.kill()
+  })
+})
diff --git a/e2e/src/selecting/share.e2e-screenshot.js b/e2e/src/selecting/share.e2e-screenshot.js
new file mode 100644
index 000000000..b3295553f
--- /dev/null
+++ b/e2e/src/selecting/share.e2e-screenshot.js
@@ -0,0 +1,61 @@
+const { AtlasPage } = require('../util')
+const { ARIA_LABELS } = require('../../../common/constants')
+const fs = require('fs')
+const path = require('path')
+
+const outputDir = path.join(__dirname, '../../../docs/autogen_images')
+const exists = fs.existsSync(outputDir)
+if (!exists) fs.mkdirSync(outputDir)
+
+describe('> share', () => {
+  let iavPage
+  beforeEach(async () => {
+    iavPage = new AtlasPage()
+    await iavPage.init()
+    await iavPage.goto()
+    await iavPage.selectTitleCard('Big Brain (Histology)')
+    await iavPage.wait(1000)
+    await iavPage.waitUntilAllChunksLoaded()
+  })
+
+  it('> generating highlight share btn', async () => {
+    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
+
+    const outputPath = path.join(outputDir, 'share_highlightShareBtn.png')
+    fs.writeFileSync(outputPath, b64, 'base64')
+  })
+
+  it('> generating highlight shareUrl btn', async () => {
+    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
+    await iavPage.wait(1000)
+
+    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_COPY_URL_CLIPBOARD}"]`)
+
+    const outputPath = path.join(outputDir, 'share_highlightShareURL.png')
+    fs.writeFileSync(outputPath, b64, 'base64')
+  })
+
+  it('> generating highlight custom URL', async () => {
+
+    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
+    await iavPage.wait(1000)
+
+    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL}"]`)
+
+    const outputPath = path.join(outputDir, 'share_highlightShareCustomURL.png')
+    fs.writeFileSync(outputPath, b64, 'base64')
+  })
+
+  it('> generating custom URL dialog', async () => {
+
+    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_BTN}"]`)
+    await iavPage.wait(1000)
+    await iavPage.click(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL}"]`)
+    await iavPage.wait(1000)
+
+    const b64 = await iavPage.takeScreenshot(`[aria-label="${ARIA_LABELS.SHARE_CUSTOM_URL_DIALOG}"]`)
+
+    const outputPath = path.join(outputDir, 'share_shareCustomURLDialog.png')
+    fs.writeFileSync(outputPath, b64, 'base64')
+  })
+})
diff --git a/e2e/src/util.js b/e2e/src/util.js
index 679cbffe2..4956f0936 100644
--- a/e2e/src/util.js
+++ b/e2e/src/util.js
@@ -5,6 +5,7 @@ const USE_SELENIUM = !!process.env.SELENIUM_ADDRESS
 if (ATLAS_URL.length === 0) throw new Error(`ATLAS_URL must either be left unset or defined.`)
 if (ATLAS_URL[ATLAS_URL.length - 1] === '/') throw new Error(`ATLAS_URL should not trail with a slash: ${ATLAS_URL}`)
 const { By, WebDriver, Key } = require('selenium-webdriver')
+const CITRUS_LIGHT_URL = `https://unpkg.com/citruslight@0.0.2/citruslight.js`
 
 function getActualUrl(url) {
   return /^http\:\/\//.test(url) ? url : `${ATLAS_URL}/${url.replace(/^\//, '')}`
@@ -48,6 +49,35 @@ class WdBase{
     return this._browser.driver
   }
 
+  // without image header
+  // output as b64 png
+  async takeScreenshot(cssSelector){
+    
+    if(cssSelector) {
+      await this._browser.executeAsyncScript(async () => {
+        const cb = arguments[arguments.length - 1]
+        const moduleUrl = arguments[0]
+        const cssSelector = arguments[1]
+
+        const el = document.querySelector(cssSelector)
+        if (!el) throw new Error(`css selector not fetching anything`)
+        import(moduleUrl)
+          .then(async m => {
+            m.citruslight(el)
+            cb()
+          })
+      }, CITRUS_LIGHT_URL, cssSelector)
+    }
+    await this.wait(1000)
+    const result = await this._browser.takeScreenshot()
+    return result
+  }
+
+  async click(cssSelector){
+    if (!cssSelector) throw new Error(`click method needs to define a css selector`)
+    await this._browser.findElement( By.css(cssSelector) ).click()
+  }
+
   historyBack() {
     return this._browser.navigate().back()
   }
diff --git a/mkdocs.yml b/mkdocs.yml
index 0a43acdc0..12153a9d1 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -23,12 +23,14 @@ pages:
     - Searching: 'usage/search.md'
     - Exploring connectivity: 'usage/connectivity.md'
     - Miscellaneous: 'usage/misc.md'
+    - Sharing: 'usage/sharing.md'
   - Advanced usage:
     - Keyboard shortcuts: 'advanced/keyboard.md'
     - URL parsing: 'advanced/url.md'
     - Fetching datasets: 'advanced/datasets.md'
     - Display non-atlas volumes: 'advanced/otherVolumes.md'
   - Release notes:
+    - v2.2.0: 'releases/v2.2.0.md'
     - v2.1.0: 'releases/v2.1.0.md'
     - v2.0.2: 'releases/v2.0.2.md'
     - v2.0.1: 'releases/v2.0.1.md'
diff --git a/package.json b/package.json
index 6332a0cce..5028d50f7 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
     "eslint": "^6.8.0",
     "eslint-plugin-html": "^6.0.0",
     "file-loader": "^1.1.11",
+    "glob": "^7.1.6",
     "hammerjs": "^2.0.8",
     "html-webpack-plugin": "^3.2.0",
     "html2canvas": "^1.0.0-rc.1",
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.component.ts b/src/ui/nehubaContainer/statusCard/statusCard.component.ts
index f64f9c3ee..e75437099 100644
--- a/src/ui/nehubaContainer/statusCard/statusCard.component.ts
+++ b/src/ui/nehubaContainer/statusCard/statusCard.component.ts
@@ -7,6 +7,7 @@ import { Observable, Subscription, of, combineLatest, BehaviorSubject } from "rx
 import { distinctUntilChanged, shareReplay, map, filter, startWith } from "rxjs/operators";
 import { MatBottomSheet } from "@angular/material/bottom-sheet";
 import { MatDialog } from "@angular/material/dialog";
+import { ARIA_LABELS } from 'common/constants'
 
 @Component({
   selector : 'ui-status-card',
@@ -26,6 +27,11 @@ export class StatusCardComponent implements OnInit, OnChanges{
   public navVal$: Observable<string>
   public mouseVal$: Observable<string>
 
+  public SHARE_BTN_ARIA_LABEL = ARIA_LABELS.SHARE_BTN
+  public COPY_URL_TO_CLIPBOARD_ARIA_LABEL = ARIA_LABELS.SHARE_COPY_URL_CLIPBOARD
+  public SHARE_CUSTOM_URL_ARIA_LABEL = ARIA_LABELS.SHARE_CUSTOM_URL
+  public SHARE_CUSTOM_URL_DIALOG_ARIA_LABEL = ARIA_LABELS.SHARE_CUSTOM_URL_DIALOG
+
   constructor(
     private store: Store<ViewerStateInterface>,
     private log: LoggingService,
@@ -157,7 +163,10 @@ export class StatusCardComponent implements OnInit, OnChanges{
     })
   }
 
-  openDialog(tmpl: TemplateRef<any>) {
-    this.dialog.open(tmpl)
+  openDialog(tmpl: TemplateRef<any>, options) {
+    const { ariaLabel } = options
+    this.dialog.open(tmpl, {
+      ariaLabel
+    })
   }
 }
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.template.html b/src/ui/nehubaContainer/statusCard/statusCard.template.html
index fbb52fae9..b7baf4061 100644
--- a/src/ui/nehubaContainer/statusCard/statusCard.template.html
+++ b/src/ui/nehubaContainer/statusCard/statusCard.template.html
@@ -67,6 +67,7 @@
       <div class="w-0 position-relative">
         <button
           (click)="showBottomSheet(shareTmpl)"
+          [attr.aria-label]="SHARE_BTN_ARIA_LABEL"
           mat-icon-button
           class="position-absolute share-btn">
           <i class="fas fa-share-square"></i>
@@ -95,7 +96,9 @@
     Share via
   </h4>
   <mat-nav-list>
-    <mat-list-item iav-clipboard-copy>
+    <mat-list-item iav-clipboard-copy
+      [attr.aria-label]="COPY_URL_TO_CLIPBOARD_ARIA_LABEL"
+      [attr.tab-index]="10">
       <mat-icon
         class="mr-4"
         fontSet="fas"
@@ -105,7 +108,9 @@
         Copy link to this view
       </span>
     </mat-list-item>
-    <mat-list-item (click)="openDialog(shareSaneUrl)">
+    <mat-list-item (click)="openDialog(shareSaneUrl, { ariaLabel: SHARE_CUSTOM_URL_DIALOG_ARIA_LABEL })"
+      [attr.aria-label]="SHARE_CUSTOM_URL_ARIA_LABEL"
+      [attr.tab-index]="10">
       <mat-icon 
         class="mr-4"
         fontSet="fas"
-- 
GitLab