[
  {
    "path": ".bluemix/deploy.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"messages\": {\n       \"$i18n\": \"locales.yml\"\n    },\n     \"title\": {\n      \"$ref\": \"#/messages/deploy.title\"\n    },\n    \"description\": {\n      \"$ref\": \"#/messages/deploy.description\"\n    },\n    \"longDescription\": {\n      \"$ref\": \"#/messages/deploy.longDescription\"\n    },\n    \"type\": \"object\",\n    \"properties\": {\n       \"api-key\": {\n            \"description\": \"The IBM Cloud API key is used to access the IBM Container Service API and interact with the cluster. You can obtain your API key with 'bx iam api-key-create' or via the console at https://console.ng.bluemix.net/iam/#/apikeys by clicking **Create API key** (Each API key only can be viewed once).\",\n            \"type\": \"string\",\n            \"pattern\": \"\\\\S\"\n        },\n       \"registry-region\": {\n          \"description\": \"The IBM Cloud region for image registry\",\n          \"type\": \"string\",\n          \"disabled\": false\n        },\n       \"registry-namespace\": {\n          \"description\": \"The namespace in the container image registry. You can set it up with {bx cr namespace-add]. Learn more at https://console.bluemix.net/docs/services/Registry/index.html .\",\n          \"type\": \"string\",\n          \"pattern\": \"^[a-z0-9][a-z0-9_]{3,29}$\"\n        },\n        \"prod-region\": {\n            \"description\": \"The IBM Cloud region for prod deployment\",\n            \"type\": \"string\",\n            \"disabled\": false\n        },\n       \"prod-cluster-name\": {\n            \"description\": \"The name of prod cluster. Retrieve it with [bx cs clusters] or via the console at https://console.ng.bluemix.net/containers-kubernetes/home/clusters .\",\n            \"type\": \"string\",\n            \"pattern\": \"\\\\S\"\n        },\n        \"prod-cluster-namespace\": {\n          \"description\": \"Prod namespace\",\n          \"type\": \"string\",\n          \"pattern\": \"\\\\S\"\n        },\n       \"app-name\": {\n            \"description\": {\n              \"$ref\": \"#/messages/deploy.appDescription\"\n            },\n            \"type\": \"string\",\n            \"pattern\": \"\\\\S\"\n        }\n    },\n    \"required\": [\"app-name\", \"api-key\", \"registry-region\", \"registry-namespace\", \"prod-region\", \"prod-cluster-name\", \"prod-cluster-namespace\"],\n    \"form\": [\n       {\n          \"type\": \"validator\",\n          \"url\": \"/devops/setup/bm-helper/custom_helper.html\"\n       },{\n          \"type\": \"text\",\n          \"readonly\": false,\n          \"title\": {\n            \"$ref\": \"#/messages/deploy.appName\"\n          },\n          \"key\": \"app-name\"\n        },{\n            \"type\": \"password\",\n            \"readonly\": false,\n            \"title\": \"IBM Cloud API key\",\n            \"key\": \"api-key\"\n          },\n        {\n          \"type\": \"table\",\n          \"columnCount\": 3,\n            \"widths\": [\"50%\", \"3%\", \"47%\"],\n            \"items\": [\n                {\n                  \"type\": \"label\",\n                  \"title\": \"Container registry region\"\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"Container registry namespace\"\n                },{\n                  \"type\": \"select\",\n                  \"title\": \"Container image registry region\",\n                  \"key\": \"registry-region\"\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },{\n                  \"type\": \"select\",\n                  \"readonly\": false,\n                  \"title\": \"Container image registry namespace\",\n                  \"key\": \"registry-namespace\"\n                }\n            ]\n        },{\n            \"type\": \"table\",\n            \"columnCount\": 5,\n            \"widths\": [\"32%\",\"2%\",\"32%\", \"2%\", \"32%\"],\n            \"items\": [\n                {\n                  \"type\": \"label\",\n                  \"title\": {\n                    \"$ref\": \"#/messages/region\"\n                  }\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },\n                {\n                  \"type\": \"label\",\n                  \"title\": \"Cluster name\"\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },\n                {\n                  \"type\": \"label\",\n                  \"title\": \"Cluster namespace\"\n                },{\n                  \"type\": \"select\",\n                  \"key\": \"prod-region\"\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },\n                {\n                  \"type\": \"select\",\n                  \"key\": \"prod-cluster-name\",\n                  \"readonly\": false\n                },{\n                  \"type\": \"label\",\n                  \"title\": \"\"\n                },\n                {\n                  \"type\": \"text\",\n                  \"key\": \"prod-cluster-namespace\",\n                  \"readonly\": false\n                }\n            ]\n        },{\n          \"type\": \"table\",\n          \"columnCount\": 1,\n            \"widths\": [\"100%\"],\n            \"items\": [\n                {\n                  \"type\": \"label\",\n                  \"title\": \"Retrieve the Kubernetes cluster name with the CLI command 'bx cs clusters' or via the [console](https://console.bluemix.net/containers-kubernetes/home/clusters).\"\n                }\n            ]\n        },{\n          \"type\": \"table\",\n          \"columnCount\": 1,\n            \"widths\": [\"100%\"],\n            \"items\": [\n               {\n                  \"type\": \"label\",\n                  \"title\": \"If the cluster namespace doesn't exist already, it will be automatically created and configured.\"\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": ".bluemix/locales.yml",
    "content": "---\r\nroot:\r\n  $ref: ./nls/messages.yml\r\n# de:\r\n#   $ref: ./nls/messages_de.yml\r\n# en-AA:\r\n#   $ref: ./nls/messages_en_AA.yml\r\n# en-RR:\r\n#   $ref: ./nls/messages_en_RR.yml\r\n# en-ZZ:\r\n#   $ref: ./nls/messages_en_ZZ.yml\r\n# es:\r\n#   $ref: ./nls/messages_es.yml\r\n# fr:\r\n#   $ref: ./nls/messages_fr.yml\r\n# it:\r\n#   $ref: ./nls/messages_it.yml\r\n# ja:\r\n#   $ref: ./nls/messages_ja.yml\r\n# ko:\r\n#   $ref: ./nls/messages_ko.yml\r\n# pt-BR:\r\n#   $ref: ./nls/messages_pt_BR.yml\r\n# zh:\r\n#   $ref: ./nls/messages_zh.yml\r\n# zh-HK:\r\n#   $ref: ./nls/messages_zh_HK.yml\r\n# zh-TW:\r\n#   $ref: ./nls/messages_zh_TW.yml\r\n"
  },
  {
    "path": ".bluemix/nls/messages.yml",
    "content": "---\r\n#The format for creating a link with a URL and text is [link text](link url) with no spaces or characters between the two sets of brackets- []()\r\ntemplate.name: \"Develop a Kubernetes app with Helm\"\r\ntemplate.description: \"With this toolchain, you can develop a Docker application and its Helm chart together in source control and have it built and deployed automatically to a Kubernetes cluster. The toolchain performs sanity checks prior to building or deploying and ensures privacy by using a private container registry and namespaces for the container registry and the Kubernetes cluster. This toolchain is also leveraging [Vulnerability Advisor](https://www.ibm.com/blogs/bluemix/2016/06/docker-container-security-with-vulnerability-advisor/), to ensure only secure images get deployed.\\n\\nBy default, the toolchain uses a sample Node.js \\\"Hello World\\\" app, but you can link to your own Git repository instead as long as it has a Dockerfile and a Helm chart.\\n\\n You can manage your IBM Cloud Container clusters in the [console](https://console.ng.bluemix.net/docs/containers/cs_cluster.html#cs_cluster).\\n\\n This toolchain uses tools that are part of the Continuous Delivery service. If an instance of that service isn't already in your organization, when you click **Create**, it is automatically added at no cost to you. For more information and terms, see the [IBM Cloud catalog](/catalog/services/continuous-delivery/).\\n\\nTo get started, click **Create**.\\n\\nFor step-by-step instructions, follow the [tutorial](https://www.ibm.com/cloud/garage/tutorials/tc-simple-kube-helm).\"\r\ntemplate.gettingStarted: \" **Your toolchain is ready!**\\n**Quick start:** Commit a change to the Git repo to trigger a new Docker image build, which will be scanned for vulnerabilites and deployed with Helm to your Kubernetes cluster. For step-by-step instructions, see the [tutorial](https://www.ibm.com/cloud/garage/tutorials/tc-simple-kube-helm?task=2) for this toolchain.\"\r\ndeploy.title: \"Innovate Deploy Stage\"\r\ndeploy.description: \"Innovate simple toolchain\"\r\ndeploy.longDescription: \"The Delivery Pipeline automates continuous build, test and deploy of the Docker application.\"\r\ndeploy.appDescription: \"The name of your app\"\r\ndeploy.appName: \"App name\"\r\nregion: \"Cluster region\"\r\norganization: \"Organization\"\r\nspace: \"Space\"\r\nprodStage: \"Production environment\"\r\n"
  },
  {
    "path": ".bluemix/pipeline.yml",
    "content": "---\nstages:\n- name: BUILD\n  inputs:\n  - type: git\n    branch: master\n    service: ${GIT_REPO}\n  triggers:\n  - type: commit\n  jobs:\n  - name: Pre-build check\n    type: builder\n    build_type: cr\n    artifact_dir: ''\n    target:\n      region_id: ${REGISTRY_REGION_ID}\n      api_key: ${API_KEY}\n    namespace: ${REGISTRY_NAMESPACE}\n    image_name: ${CF_APP_NAME}\n    script: |-\n      #********************************************\n      #!/bin/bash\n      # uncomment to debug the script\n      #set -x\n      # copy the script below into your app code repo (e.g. ./scripts/check_prebuild.sh) and 'source' it from your pipeline job\n      #    source ./scripts/check_prebuild.sh\n      # alternatively, you can source it from online script:\n      #    source <(curl -sSL \"https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_prebuild.sh\")\n      # ------------------\n      # source: https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_prebuild.sh\n      export TOOLCHAIN_FLAG=active\n      echo \"Build environment variables:\"\n      echo \"REGISTRY_URL=${REGISTRY_URL}\"\n      echo \"TOOLCHAIN_FLAG=${TOOLCHAIN_FLAG}\"\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\"\n      echo \"IMAGE_NAME=${IMAGE_NAME}\"\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\"\n      echo \"ARCHIVE_DIR=${ARCHIVE_DIR}\"\n      # also run 'env' command to find all available env variables\n      # or learn more about the available environment variables at:\n      # https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment\n\n      echo \"==========================================================\"\n      echo \"CHECKING DOCKERFILE\"\n      echo \"Checking Dockerfile at the repository root\"\n      if [ -f Dockerfile ]; then\n        echo \"Dockerfile found\"\n      else\n          echo \"Dockerfile not found\"\n          exit 1\n      fi\n      echo \"Linting Dockerfile\"\n      npm install -g dockerlint\n      dockerlint -f Dockerfile\n\n      echo \"==========================================================\"\n      echo \"CHECKING HELM CHART\"\n      echo \"Looking for chart under /chart/<CHART_NAME>\"\n      if [ -d ./chart ]; then\n        CHART_NAME=$(find chart/. -maxdepth 2 -type d -name '[^.]?*' -printf %f -quit)\n      fi\n      if [ -z \"${CHART_NAME}\" ]; then\n          echo -e \"No Helm chart found for Kubernetes deployment under /chart/<CHART_NAME>.\"\n          exit 1\n      else\n          echo -e \"Helm chart found for Kubernetes deployment : /chart/${CHART_NAME}\"\n      fi\n      echo \"Linting Helm Chart\"\n      helm lint ./chart/${CHART_NAME}\n\n      echo \"==========================================================\"\n      echo \"CHECKING REGISTRY current plan and quota\"\n      ibmcloud cr plan\n      ibmcloud cr quota\n      echo \"If needed, discard older images using: ibmcloud cr image-rm\"\n\n      echo \"Current content of image registry\"\n      ibmcloud cr images\n\n      echo \"Checking registry namespace: ${REGISTRY_NAMESPACE}\"\n      NS=$( ibmcloud cr namespaces | grep ${REGISTRY_NAMESPACE} ||: )\n      if [ -z \"${NS}\" ]; then\n          echo \"Registry namespace ${REGISTRY_NAMESPACE} not found, creating it.\"\n          ibmcloud cr namespace-add ${REGISTRY_NAMESPACE}\n          echo \"Registry namespace ${REGISTRY_NAMESPACE} created.\"\n      else\n          echo \"Registry namespace ${REGISTRY_NAMESPACE} found.\"\n      fi\n  - name: Build Docker image\n    type: builder\n    build_type: cr\n    artifact_dir: output\n    target:\n      region_id: ${REGISTRY_REGION_ID}\n      api_key: ${API_KEY}\n    namespace: ${REGISTRY_NAMESPACE}\n    image_name: ${CF_APP_NAME}\n    script: |\n      #!/bin/bash\n      # uncomment to debug the script\n      #set -x\n      # copy the script below into your app code repo (e.g. ./scripts/build_image.sh) and 'source' it from your pipeline job\n      #    source ./scripts/build_image.sh\n      # alternatively, you can source it from online script:\n      #    source <(curl -sSL \"https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/build_image.sh\")\n      # ------------------\n      # source: https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/build_image.sh\n      echo \"Build environment variables:\"\n      export TOOLCHAIN_FLAG=active\n      echo \"TOOLCHAIN_FLAG=${TOOLCHAIN_FLAG}\"\n      echo \"REGISTRY_URL=${REGISTRY_URL}\"\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\"\n      echo \"IMAGE_NAME=${IMAGE_NAME}\"\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\"\n      echo \"ARCHIVE_DIR=${ARCHIVE_DIR}\"\n      # also run 'env' command to find all available env variables\n      # or learn more about the available environment variables at:\n      # https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment\n\n      # To review or change build options use:\n      # ibmcloud cr build --help\n\n      echo -e \"Existing images in registry\"\n      ibmcloud cr images\n\n      echo \"==========================================================\"\n      echo -e \"BUILDING CONTAINER IMAGE: ${IMAGE_NAME}:${BUILD_NUMBER}\"\n      set -x\n      ibmcloud cr build -t ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${BUILD_NUMBER} .\n      set +x\n      ibmcloud cr image-inspect ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${BUILD_NUMBER}\n\n      # When 'ibmcloud' commands are in the pipeline job config directly, the image URL will automatically be passed\n      # along with the build result as env variable PIPELINE_IMAGE_URL to any subsequent job consuming this build result.\n      # When the job is sourc'ing an external shell script, or to pass a different image URL than the one inferred by the pipeline,\n      # please uncomment and modify the environment variable the following line.\n      export PIPELINE_IMAGE_URL=\"$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$BUILD_NUMBER\"\n      echo \"TODO - remove once no longer needed to unlock VA job ^^^^\"\n\n      ibmcloud cr images\n\n      echo \"==========================================================\"\n      echo \"COPYING ARTIFACTS needed for deployment and testing (in particular build.properties)\"\n\n      echo \"Checking archive dir presence\"\n      mkdir -p $ARCHIVE_DIR\n\n      # Persist env variables into a properties file (build.properties) so that all pipeline stages consuming this\n      # build as input and configured with an environment properties file valued 'build.properties'\n      # will be able to reuse the env variables in their job shell scripts.\n\n      # CHART information from build.properties is used in Helm Chart deployment to set the release name\n      CHART_NAME=$(find chart/. -maxdepth 2 -type d -name '[^.]?*' -printf %f -quit)\n      echo \"CHART_NAME=${CHART_NAME}\" >> $ARCHIVE_DIR/build.properties\n      # IMAGE information from build.properties is used in Helm Chart deployment to set the release name\n      echo \"IMAGE_NAME=${IMAGE_NAME}\" >> $ARCHIVE_DIR/build.properties\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\" >> $ARCHIVE_DIR/build.properties\n      # REGISTRY information from build.properties is used in Helm Chart deployment to generate cluster secret\n      echo \"REGISTRY_URL=${REGISTRY_URL}\" >> $ARCHIVE_DIR/build.properties\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\" >> $ARCHIVE_DIR/build.properties\n      echo \"File 'build.properties' created for passing env variables to subsequent pipeline jobs:\"\n      cat $ARCHIVE_DIR/build.properties\n\n      echo \"Copy pipeline scripts along with the build\"\n      # Copy scripts (incl. deploy scripts)\n      if [ -d ./scripts/ ]; then\n        if [ ! -d $ARCHIVE_DIR/scripts/ ]; then # no need to copy if working in ./ already\n          cp -r ./scripts/ $ARCHIVE_DIR/\n        fi\n      fi\n\n      echo \"Copy Helm chart along with the build\"\n      if [ ! -d $ARCHIVE_DIR/chart/ ]; then # no need to copy if working in ./ already\n        cp -r ./chart/ $ARCHIVE_DIR/\n      fi\n- name: VALIDATE\n  inputs:\n  - type: job\n    stage: BUILD\n    job: Build Docker image\n  triggers:\n  - type: stage\n  properties:\n  - name: buildprops\n    value: build.properties\n    type: file\n  jobs:\n  - name: Vulnerability Advisor\n    type: tester\n    test_type: vulnerabilityadvisor\n    use_image_from_build_input: true\n    fail_stage: false\n    target:\n      region_id: ${REGISTRY_REGION_ID}\n      api_key: ${API_KEY}\n    script: |\n      #!/bin/bash\n      # uncomment to debug the script\n      # set -x\n      # copy the script below into your app code repo (e.g. ./scripts/check_vulnerabilities.sh) and 'source' it from your pipeline job\n      #    source ./scripts/check_vulnerabilities.sh\n      # alternatively, you can source it from online script:\n      #    source <(curl -sSL \"https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_vulnerabilities.sh\")\n      # ------------------\n      # source: https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_vulnerabilities.sh\n      # Input env variables (can be received via a pipeline environment properties.file.\n      echo \"CHART_NAME=${CHART_NAME}\"\n      echo \"IMAGE_NAME=${IMAGE_NAME}\"\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\"\n      echo \"REGISTRY_URL=${REGISTRY_URL}\"\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\"\n      #View build properties\n      # cat build.properties\n      # also run 'env' command to find all available env variables\n      # or learn more about the available environment variables at:\n      # https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment\n\n      ibmcloud cr images\n      PIPELINE_IMAGE_URL=$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$BUILD_NUMBER\n      echo -e \"Checking vulnerabilities in image: ${PIPELINE_IMAGE_URL}\"\n      for ITER in {1..30}\n      do\n        set +e\n        STATUS=$( ibmcloud cr va -e -o json ${PIPELINE_IMAGE_URL} | jq '.[0].status' )\n        set -e\n        if [[ ${STATUS} == *OK* ]]; then\n          break\n        fi\n        echo -e \"${ITER} STATUS ${STATUS} : A vulnerability report was not found for the specified image.\"\n        echo \"Either the image doesn't exist or the scan hasn't completed yet. \"\n        echo \"Waiting for scan to complete..\"\n        sleep 10\n      done\n      set +e\n      ibmcloud cr va ${PIPELINE_IMAGE_URL}\n      set -e\n      [[ $(ibmcloud cr va -e -o json ${PIPELINE_IMAGE_URL} | jq '.[0].status') == *OK* ]] || { echo \"ERROR: The vulnerability scan was not successful, check the OUTPUT of the command and try again.\"; exit 1; }\n- name: PROD\n  inputs:\n  - type: job\n    stage: BUILD\n    job: Build Docker image\n  triggers:\n  - type: stage\n  properties:\n  - name: buildprops\n    value: build.properties\n    type: file\n  - name: CLUSTER_NAMESPACE\n    value: ${PROD_CLUSTER_NAMESPACE}\n    type: text\n  jobs:\n  - name: Pre-deploy check\n    type: deployer\n    target:\n      region_id: ${PROD_REGION_ID}\n      api_key: ${API_KEY}\n      kubernetes_cluster: ${PROD_CLUSTER_NAME}\n    script: |\n      #!/bin/bash\n      # uncomment to debug the script\n      #set -x\n      # copy the script below into your app code repo (e.g. ./scripts/check_predeploy.sh) and 'source' it from your pipeline job\n      #    source ./scripts/check_predeploy.sh\n      # alternatively, you can source it from online script:\n      #    source <(curl -sSL \"https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_predeploy.sh\")\n      # ------------------\n      # source: https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/check_predeploy.sh\n      # Input env variables (can be received via a pipeline environment properties.file.\n      echo \"CHART_NAME=${CHART_NAME}\"\n      echo \"IMAGE_NAME=${IMAGE_NAME}\"\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\"\n      echo \"REGISTRY_URL=${REGISTRY_URL}\"\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\"\n            #View build properties\n      # cat build.properties\n      # also run 'env' command to find all available env variables\n      # or learn more about the available environment variables at:\n      # https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment\n\n      # Input env variables from pipeline job\n      echo \"PIPELINE_KUBERNETES_CLUSTER_NAME=${PIPELINE_KUBERNETES_CLUSTER_NAME}\"\n      echo \"CLUSTER_NAMESPACE=${CLUSTER_NAMESPACE}\"\n\n      #Check cluster availability\n      echo \"==========================================================\"\n      echo \"CHECKING CLUSTER readiness and namespace existence\"\n      IP_ADDR=$(ibmcloud cs workers ${PIPELINE_KUBERNETES_CLUSTER_NAME} | grep normal | awk '{ print $2 }')\n      if [ -z \"${IP_ADDR}\" ]; then\n        echo -e \"${PIPELINE_KUBERNETES_CLUSTER_NAME} not created or workers not ready\"\n        exit 1\n      fi\n      echo \"Configuring cluster namespace\"\n      if kubectl get namespace ${CLUSTER_NAMESPACE}; then\n        echo -e \"Namespace ${CLUSTER_NAMESPACE} found.\"\n      else\n        kubectl create namespace ${CLUSTER_NAMESPACE}\n        echo -e \"Namespace ${CLUSTER_NAMESPACE} created.\"\n      fi\n\n      echo \"==========================================================\"\n\n      echo \"Checking if conversation service exists\"\n\n      echo \"1\" | echo \"\\n\" | echo \"1\" | ibmcloud target --cf\n      export CONV_SERVICE_CHECK=$(ibmcloud service show innovate-conversation-service | grep \"FAILED\")\n      echo \"Check: $CONV_SERVICE_CHECK\"\n\n      if [ ${CONV_SERVICE_CHECK} == \"FAILED\" ]; then\n        echo \"Conversation service does not exist, creating\"\n        ibmcloud service create conversation free innovate-conversation-service\n      fi\n\n      # Grant access to private image registry from namespace $CLUSTER_NAMESPACE\n      # reference https://console.bluemix.net/docs/containers/cs_cluster.html#ibmcloud_registry_other\n      echo \"==========================================================\"\n      echo -e \"CONFIGURING ACCESS to private image registry from namespace ${CLUSTER_NAMESPACE}\"\n      IMAGE_PULL_SECRET_NAME=\"ibmcloud-toolchain-${PIPELINE_TOOLCHAIN_ID}-${REGISTRY_URL}\"\n      echo -e \"Checking for presence of ${IMAGE_PULL_SECRET_NAME} imagePullSecret for this toolchain\"\n      if ! kubectl get secret ${IMAGE_PULL_SECRET_NAME} --namespace ${CLUSTER_NAMESPACE}; then\n        echo -e \"${IMAGE_PULL_SECRET_NAME} not found in ${CLUSTER_NAMESPACE}, creating it\"\n        # for Container Registry, docker username is 'token' and email does not matter\n        kubectl --namespace ${CLUSTER_NAMESPACE} create secret docker-registry ${IMAGE_PULL_SECRET_NAME} --docker-server=${REGISTRY_URL} --docker-password=${PIPELINE_BLUEMIX_API_KEY} --docker-username=iamapikey --docker-email=a@b.com\n      else\n        echo -e \"Namespace ${CLUSTER_NAMESPACE} already has an imagePullSecret for this toolchain.\"\n      fi\n      echo \"Checking ability to pass pull secret via Helm chart\"\n      CHART_PULL_SECRET=$( grep 'pullSecret' ./chart/${CHART_NAME}/values.yaml || : )\n      if [ -z \"$CHART_PULL_SECRET\" ]; then\n        echo \"WARNING: Chart is not expecting an explicit private registry imagePullSecret. Will patch the cluster default serviceAccount to pass it implicitly for now.\"\n        echo \"Going forward, you should edit the chart to add in:\"\n        echo -e \"[./chart/${CHART_NAME}/templates/deployment.yaml] (under kind:Deployment)\"\n        echo \"    ...\"\n        echo \"    spec:\"\n        echo \"      imagePullSecrets:               #<<<<<<<<<<<<<<<<<<<<<<<<\"\n        echo \"        - name: {{ .Values.image.pullSecret }}   #<<<<<<<<<<<<<<<<<<<<<<<<\"\n        echo \"      containers:\"\n        echo \"        - name: {{ .Chart.Name }}\"\n        echo \"          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        echo \"    ...\"\n        echo -e \"[./chart/${CHART_NAME}/values.yaml]\"\n        echo \"or check out this chart example: https://github.com/open-toolchain/hello-helm/tree/master/chart/hello\"\n        echo \"or refer to: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-pod-that-uses-your-secret\"\n        echo \"    ...\"\n        echo \"    image:\"\n        echo \"repository: webapp\"\n        echo \"  tag: 1\"\n        echo \"  pullSecret: regsecret            #<<<<<<<<<<<<<<<<<<<<<<<<\"\"\n        echo \"  pullPolicy: IfNotPresent\"\n        echo \"    ...\"\n        echo \"Enabling default serviceaccount to use the pull secret\"\n        kubectl patch -n ${CLUSTER_NAMESPACE} serviceaccount/default -p '{\"imagePullSecrets\":[{\"name\":\"'\"${IMAGE_PULL_SECRET_NAME}\"'\"}]}'\n        echo \"default serviceAccount:\"\n        kubectl get serviceAccount default -o yaml\n        echo -e \"Namespace ${CLUSTER_NAMESPACE} authorizing with private image registry using patched default serviceAccount\"\n      else\n        echo -e \"Namespace ${CLUSTER_NAMESPACE} authorizing with private image registry using Helm chart imagePullSecret\"\n      fi\n\n      echo \"==========================================================\"\n      echo \"CONFIGURING TILLER enabled (Helm server-side component)\"\n      helm init --upgrade\n      kubectl rollout status -w deployment/tiller-deploy --namespace=kube-system\n      helm version\n\n      echo \"==========================================================\"\n      echo -e \"CHECKING HELM releases in this namespace: ${CLUSTER_NAMESPACE}\"\n      helm list --namespace ${CLUSTER_NAMESPACE}\n  - name: Deploy Helm chart\n    type: deployer\n    target:\n      region_id: ${PROD_REGION_ID}\n      api_key: ${API_KEY}\n      kubernetes_cluster: ${PROD_CLUSTER_NAME}\n    script: |\n      #!/bin/bash\n      # uncomment to debug the script\n      #set -x\n      # copy the script below into your app code repo (e.g. ./scripts/deploy_helm.sh) and 'source' it from your pipeline job\n      #    source ./scripts/deploy_helm.sh\n      # alternatively, you can source it from online script:\n      #    source <(curl -sSL \"https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/deploy_helm.sh\")\n      # ------------------\n      # source: https://raw.githubusercontent.com/open-toolchain/commons/master/scripts/deploy_helm.sh\n      # Input env variables (can be received via a pipeline environment properties.file.\n      echo \"CHART_NAME=${CHART_NAME}\"\n      echo \"IMAGE_NAME=${IMAGE_NAME}\"\n      echo \"BUILD_NUMBER=${BUILD_NUMBER}\"\n      echo \"REGISTRY_URL=${REGISTRY_URL}\"\n      echo \"REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}\"\n\n      #View build properties\n      # cat build.properties\n      # also run 'env' command to find all available env variables\n      # or learn more about the available environment variables at:\n      # https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment\n\n      # Input env variables from pipeline job\n      echo \"PIPELINE_KUBERNETES_CLUSTER_NAME=${PIPELINE_KUBERNETES_CLUSTER_NAME}\"\n      echo \"CLUSTER_NAMESPACE=${CLUSTER_NAMESPACE}\"\n\n      echo \"==========================================================\"\n      echo \"DEFINE RELEASE by prefixing image (app) name with namespace if not 'default' as Helm needs unique release names across namespaces\"\n      if [[ \"${CLUSTER_NAMESPACE}\" != \"default\" ]]; then\n        RELEASE_NAME=\"${CLUSTER_NAMESPACE}-${IMAGE_NAME}\"\n      else\n        RELEASE_NAME=${IMAGE_NAME}\n      fi\n      echo -e \"Release name: ${RELEASE_NAME}\"\n\n      echo \"==========================================================\"\n      echo \"Binding conversation service to cluster\"\n      export CONV_BINDING_CHECK=$(ibmcloud cs cluster-services ${PIPELINE_KUBERNETES_CLUSTER_NAME} --namespace ${CLUSTER_NAMESPACE} | grep \"innovate-conversation-service\")\n      echo \"Check: $CONV_BINDING_CHECK\"\n\n      if [[ $CONV_BINDING_CHECK == *\"innovate-conversation-service\"* ]]; then\n        echo \"Binding already exists, moving on\"\n      else\n        echo \"Binding does not exist, binding\"\n        ibmcloud cs cluster-service-bind ${PIPELINE_KUBERNETES_CLUSTER_NAME} ${CLUSTER_NAMESPACE} innovate-conversation-service\n      fi\n\n      echo \"==========================================================\"\n      echo \"DEPLOYING HELM chart\"\n      IP_ADDR=$(ibmcloud cs workers ${PIPELINE_KUBERNETES_CLUSTER_NAME} | grep normal | awk '{ print $2 }')\n      IMAGE_REPOSITORY=${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}\n      IMAGE_PULL_SECRET_NAME=\"ibmcloud-toolchain-${PIPELINE_TOOLCHAIN_ID}-${REGISTRY_URL}\"\n\n      # Using 'upgrade --install\" for rolling updates. Note that subsequent updates will occur in the same namespace the release is currently deployed in, ignoring the explicit--namespace argument\".\n      echo -e \"Dry run into: ${PIPELINE_KUBERNETES_CLUSTER_NAME}/${CLUSTER_NAMESPACE}.\"\n      helm upgrade --install --debug --dry-run ${RELEASE_NAME} ./chart/${CHART_NAME} --set image.repository=${IMAGE_REPOSITORY},image.tag=${BUILD_NUMBER},image.pullSecret=${IMAGE_PULL_SECRET_NAME},config.mongoUrl=mongodb://mongo:***REMOVED***@${IP_ADDR}:30443/***REMOVED***,config.basePath=${IP_ADDR} --namespace ${CLUSTER_NAMESPACE}\n\n      echo -e \"Deploying into: ${PIPELINE_KUBERNETES_CLUSTER_NAME}/${CLUSTER_NAMESPACE}.\"\n      helm upgrade  --install ${RELEASE_NAME} ./chart/${CHART_NAME} --set image.repository=${IMAGE_REPOSITORY},image.tag=${BUILD_NUMBER},image.pullSecret=${IMAGE_PULL_SECRET_NAME},config.mongoUrl=mongodb://mongo:***REMOVED***@${IP_ADDR}:30443/***REMOVED***,config.basePath=${IP_ADDR} --namespace ${CLUSTER_NAMESPACE}\n\n      echo \"==========================================================\"\n      echo -e \"CHECKING deployment status of release ${RELEASE_NAME} with image tag: ${BUILD_NUMBER}\"\n      echo \"\"\n      for ITERATION in {1..30}\n      do\n        DATA=$( kubectl get pods --namespace ${CLUSTER_NAMESPACE} -a -l release=${RELEASE_NAME} -o json )\n        NOT_READY=$( echo $DATA | jq '.items[].status.containerStatuses[] | select(.image==\"'\"${IMAGE_REPOSITORY}:${BUILD_NUMBER}\"'\") | select(.ready==false) ' )\n        if [[ -z \"$NOT_READY\" ]]; then\n          echo -e \"All pods are ready:\"\n          echo $DATA | jq '.items[].status.containerStatuses[] | select(.image==\"'\"${IMAGE_REPOSITORY}:${BUILD_NUMBER}\"'\") | select(.ready==true) '\n          break # deployment succeeded\n        fi\n        REASON=$(echo $DATA | jq '.items[].status.containerStatuses[] | select(.image==\"'\"${IMAGE_REPOSITORY}:${BUILD_NUMBER}\"'\") | .state.waiting.reason')\n        echo -e \"${ITERATION} : Deployment still pending...\"\n        echo -e \"NOT_READY:${NOT_READY}\"\n        echo -e \"REASON: ${REASON}\"\n        if [[ ${REASON} == *ErrImagePull* ]] || [[ ${REASON} == *ImagePullBackOff* ]]; then\n          echo \"Detected ErrImagePull or ImagePullBackOff failure. \"\n          echo \"Please check proper authenticating to from cluster to image registry (e.g. image pull secret)\"\n          break; # no need to wait longer, error is fatal\n        elif [[ ${REASON} == *CrashLoopBackOff* ]]; then\n          echo \"Detected CrashLoopBackOff failure. \"\n          echo \"Application is unable to start, check the application startup logs\"\n          break; # no need to wait longer, error is fatal\n        fi\n        sleep 5\n      done\n\n      if [[ ! -z \"$NOT_READY\" ]]; then\n        echo \"\"\n        echo \"==========================================================\"\n        echo \"DEPLOYMENT FAILED\"\n        echo \"Deployed Services:\"\n        kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n        echo \"\"\n        echo \"Deployed Pods:\"\n        kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n        echo \"\"\n        echo \"Application Logs\"\n        kubectl logs --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n        echo \"==========================================================\"\n        PREVIOUS_RELEASE=$( helm history ${RELEASE_NAME} | grep SUPERSEDED | sort -r -n | awk '{print $1}' | head -n 1 )\n        echo -e \"Could rollback to previous release: ${PREVIOUS_RELEASE} using command:\"\n        echo -e \"helm rollback ${RELEASE_NAME} ${PREVIOUS_RELEASE}\"\n        # helm rollback ${RELEASE_NAME} ${PREVIOUS_RELEASE}\n        # echo -e \"History for release:${RELEASE_NAME}\"\n        # helm history ${RELEASE_NAME}\n        # echo \"Deployed Services:\"\n        # kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n        # echo \"\"\n        # echo \"Deployed Pods:\"\n        # kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n        exit 1\n      fi\n\n      echo \"\"\n      echo \"==========================================================\"\n      echo \"DEPLOYMENT SUCCEEDED\"\n      echo \"\"\n      echo -e \"Status for release:${RELEASE_NAME}\"\n      helm status ${RELEASE_NAME}\n\n      echo \"\"\n      echo -e \"History for release:${RELEASE_NAME}\"\n      helm history ${RELEASE_NAME}\n\n      # echo \"\"\n      # echo \"Deployed Services:\"\n      # kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n      # echo \"\"\n      # echo \"Deployed Pods:\"\n      # kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE}\n\n      echo \"==========================================================\"\n      IP_ADDR=$(ibmcloud cs workers ${PIPELINE_KUBERNETES_CLUSTER_NAME} | grep normal | head -n 1 | awk '{ print $2 }')\n      PORT=30200\n      export MONGO_URL=mongodb://mongo:***REMOVED***@${IP_ADDR}:30443/***REMOVED***\n      echo \"Mongo connection string: ${MONGO_URL}\"\n      echo -e \"View the application at: http://${IP_ADDR}:${PORT}\"\n"
  },
  {
    "path": ".bluemix/toolchain.yml",
    "content": "version: '2'\nmessages:\n  $i18n: locales.yml\ntemplate:\n  name:\n    $ref: \"#/messages/template.name\"\n  description:\n    $ref: \"#/messages/template.description\"\n  header: '![](toolchain.svg?localize)'\n  icon: secure-lock-helm.svg\n  required:\n    - build\n    - repo\n  info:\n    git url: >-\n      [https://github.com/open-toolchain/simple-helm-toolchain](https://github.com/open-toolchain/simple-helm-toolchain)\n    git branch: >-\n      [master](https://github.com/open-toolchain/simple-helm-toolchain/tree/master)\ntoolchain:\n  name: 'innovate-toolchain'\n  template:\n    getting_started:\n      $ref: \"#/messages/template.gettingStarted\"\nservices:\n  repo:\n    service_id: hostedgit\n    parameters:\n      repo_name: 'innovate-bank'\n      repo_url: 'https://github.com/IBM/innovate-digital-bank'\n      type: clone\n      has_issues: true\n      enable_traceability: true\n  build:\n    service_id: pipeline\n    parameters:\n      services:\n        - repo\n      name: 'innovate-bank'\n      ui-pipeline: true\n      configuration:\n        content:\n          $text: pipeline.yml\n        env:\n          GIT_REPO: repo\n          CF_APP_NAME: '{{form.pipeline.parameters.app-name}}'\n          REGISTRY_REGION_ID: '{{form.pipeline.parameters.registry-region}}'\n          REGISTRY_NAMESPACE: '{{form.pipeline.parameters.registry-namespace}}'\n          API_KEY: '{{form.pipeline.parameters.api-key}}'\n          PROD_REGION_ID: '{{form.pipeline.parameters.prod-region}}'\n          PROD_CLUSTER_NAME: '{{form.pipeline.parameters.prod-cluster-name}}'\n          PROD_CLUSTER_NAMESPACE: '{{form.pipeline.parameters.prod-cluster-namespace}}'\n        execute: true\n  webide:\n    service_id: orion\nform:\n  pipeline:\n    parameters:\n      app-name: '{{services.repo.parameters.repo_name}}'\n      prod-cluster-namespace: prod\n    schema:\n      $ref: deploy.json\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\nnode_modules_linux/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\nbuildContext.tar\npackage-lock.json\n"
  },
  {
    "path": ".ibm-project",
    "content": "{\"build-release-ready\":false,\"build-debug-ready\":true,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"tokyo-k8s\"}"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js: 8\nsudo: required\ngroup: stable\ndist: trusty\nos: linux\n\nservices:\n  - docker\n\naddons:\n  apt:\n    sources:\n      - debian-sid\n\ninstall:\n  - \"npm -g install npm\"\n  - \"./scripts/install_bx.sh\"\n\nbefore-script:\n  - \"sudo apt-get install cabal-install\"\n  - \"cabal update\"\n  - \"cabal install shellcheck\"\n\nscript: \"npm test\"\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nThis is an open source project, and we appreciate your help!\n\nWe use the GitHub issue tracker to discuss new features and non-trivial bugs.\n\nIn addition to the issue tracker, [#journeys on\nSlack](https://dwopen.slack.com) is the best way to get into contact with the\nproject's maintainers.\n\nTo contribute code, documentation, or tests, please submit a pull request to\nthe GitHub repository. Generally, we expect two maintainers to review your pull\nrequest before it is approved for merging. For more details, see the\n[MAINTAINERS](MAINTAINERS.md) page.\n"
  },
  {
    "path": "DOCS.md",
    "content": "# Docs\n\n## Microservices\n\n### Portal [3100:30200]\n\nLoads the UI and takes care of user sessions. Communicates with all other microservices.\n\n### Authentication [3200:30100]\n\nHandles user profile creation, as well as login & logout.\n\n#### Endpoints:\n\n##### /api/user/create\n\nDescription: Creates a new user account\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String,\n  name: String,\n  email: String,\n  phone: String,\n  gender: String,\n  dob: String,\n  eid: String,\n  password: String\n}\n```\n\n##### /api/user/authenticate\n\nDescription: Authenticates a user\n\nMethod: POST\n\nExample input:\n\n```\n{\n  email: String,\n  password: String\n}\n```\n\n##### /api/user/get\n\nDescription: Returns a list of all users\n\nMethod: GET\n\n### Accounts [3400:30120]\n\nHandles creation, management, and retrieval of a user's banking accounts.\n\n#### Endpoints:\n\n##### /api/accounts/create\n\nDescription: Creates a new user account\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String,\n  type: String,\n  currency: String,\n}\n```\nNotes:\n\nThe parameter uuid links the account to a user's unique identifier. Type has to be one of the following: current, savings, credit, prepaid\n\n##### /api/accounts/get\n\nDescription: Retrieves a user's accounts\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String\n}\n```\n\n##### /api/accounts/deposit\n\nDescription: Deposits an amount to a user's account\n\nMethod: POST\n\nExample input:\n\n```\n{\n  number: String,\n  amount: Number\n}\n```\n\nNotes:\n\nThe parameter number references an account\n\n##### /api/accounts/withdraw\n\nDescription: Withdraws an amount from a user's account\n\nMethod: POST\n\nExample input:\n\n```\n{\n  number: String,\n  amount: Number\n}\n```\n\n##### /api/accounts/drop\n\nDescription: Drops the accounts collection\n\nMethod: GET\n\n### Transactions [3600:30140]\n\nHandles creation and retrieval of transactions\n\n#### Endpoints:\n\n##### /api/transactions/create\n\nDescription: Creates a new transaction\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String,\n  amount: String,\n  currency: String,\n  description: String,\n  date: String,\n  category: String\n}\n```\n\n> Category has to be one of the following: \n> - groceries\n> - eating_out\n> - transport\n> - bills\n> - expenses\n> - cash\n> - holidays\n\n##### /api/transactions/get\n\nDescription: Retrieves a user's transactions\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String\n}\n```\n\n##### /api/transactions/drop\n\nDescription: Drops the transactions collection\n\nMethod: GET\n\n### Bills [3800:30160]\n\nHandles creation, payment, and retrieval of bills\n\n#### Endpoints:\n\n##### /api/bills/create\n\nDescription: Creates a new bill\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String,\n  category: String,\n  entity: String,\n  account_no: String,\n  amount: String,\n  date: String\n}\n```\n\n\n> Category has to be one of the following: \n> - utilities\n> - home_entertainment\n> - mobile_phone\n> - credit_card\n\n##### /api/bills/get\n\nDescription: Retrieves a user's bills\n\nMethod: POST\n\nExample input:\n\n```\n{\n  uuid: String\n}\n```\n\n##### /api/bills/drop\n\nDescription: Drops the bills collection\n\nMethod: GET\n\n### Support [4000:30180]\n\nHandles communication with Watson Assistant on IBM Cloud to enable a dummy support chat feature.\n\n### Userbase [4100:30050]\n\nSimulates a fake userbase for the app. Periodically loops through all user accounts and adds randomized bills and transactions for them.\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n# Upgrade npm to latest version\n\nRUN npm install -g yarnpkg\nRUN yarn global add npm\nRUN npm -v\nRUN npm config set unsafe-perm=true\n\n# Copy app & set working directory\nWORKDIR /app\nCOPY . /app\nRUN npm install; npm prune --production\n\nENV NODE_ENV production\nENV SESSION_SECRET ***REMOVED***\nENV MONGO_USERNAME mongo\nENV MONGO_PASSWORD ***REMOVED***\nENV MONGO_DB ***REMOVED***\n\nEXPOSE 3100 3200 3400 3600 3800 4000 4100\n\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3000\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3000\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "LICENSE.md",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [2018] [Amal Amine]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MAINTAINERS.md",
    "content": "# Maintainers Guide\n\nThis guide is intended for maintainers - anybody with commit access to one or\nmore Code Pattern repositories.\n\n## Methodology\n\nThis repository does not have a traditional release management cycle, but\nshould instead be maintained as a useful, working, and polished reference at\nall times. While all work can therefore be focused on the master branch, the\nquality of this branch should never be compromised.\n\nThe remainder of this document details how to merge pull requests to the\nrepositories.\n\n## Merge approval\n\nThe project maintainers use LGTM (Looks Good To Me) in comments on the pull\nrequest to indicate acceptance prior to merging. A change requires LGTMs from\ntwo project maintainers. If the code is written by a maintainer, the change\nonly requires one additional LGTM.\n\n## Reviewing Pull Requests\n\nWe recommend reviewing pull requests directly within GitHub. This allows a\npublic commentary on changes, providing transparency for all users. When\nproviding feedback be civil, courteous, and kind. Disagreement is fine, so long\nas the discourse is carried out politely. If we see a record of uncivil or\nabusive comments, we will revoke your commit privileges and invite you to leave\nthe project.\n\nDuring your review, consider the following points:\n\n### Does the change have positive impact?\n\nSome proposed changes may not represent a positive impact to the project. Ask\nwhether or not the change will make understanding the code easier, or if it\ncould simply be a personal preference on the part of the author (see\n[bikeshedding](https://en.wiktionary.org/wiki/bikeshedding)).\n\nPull requests that do not have a clear positive impact should be closed without\nmerging.\n\n### Do the changes make sense?\n\nIf you do not understand what the changes are or what they accomplish, ask the\nauthor for clarification. Ask the author to add comments and/or clarify test\ncase names to make the intentions clear.\n\nAt times, such clarification will reveal that the author may not be using the\ncode correctly, or is unaware of features that accommodate their needs. If you\nfeel this is the case, work up a code sample that would address the pull\nrequest for them, and feel free to close the pull request once they confirm.\n\n### Does the change introduce a new feature?\n\nFor any given pull request, ask yourself \"is this a new feature?\" If so, does\nthe pull request (or associated issue) contain narrative indicating the need\nfor the feature? If not, ask them to provide that information.\n\nAre new unit tests in place that test all new behaviors introduced? If not, do\nnot merge the feature until they are! Is documentation in place for the new\nfeature? (See the documentation guidelines). If not do not merge the feature\nuntil it is! Is the feature necessary for general use cases? Try and keep the\nscope of any given component narrow. If a proposed feature does not fit that\nscope, recommend to the user that they maintain the feature on their own, and\nclose the request. You may also recommend that they see if the feature gains\ntraction among other users, and suggest they re-submit when they can show such\nsupport.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/IBM/innovate-digital-bank.svg?branch=master)](https://travis-ci.org/IBM/innovate-digital-bank)\n\n# Building a Digital Bank with Node.js, Express, MongoDB, & Kubernetes\n\nIn this code pattern, we will build a dummy digital bank composed of a set of microservices that communicate with each other. We'll be using Node.js, Express, MongoDB, and the IBM Cloud Container Service.\n\nDevelopment of [cloud native apps](https://www.cncf.io/blog/2017/05/15/developing-cloud-native-applications/) that are broken down into a set of [microservices](http://microservices.io/) has been praised and commended as best-practice in software development methodologies. Software stacks like [Kubernetes](https://kubernetes.io/), which enable cloud native computing, have therefore picked up quite a bit of popularity.\n\nIt’s a little _(a lot)_ more fun, however, to build a so-called cloud native app, than to talk about one.\n\nSo here's our attempt:\n\nWe’ll take a use-case that has a bit of real-world familiarity to it — A digital bank. Naturally inspired by [Monzo](http://monzo.com/). Let’s call it Innovate.\n\n[A live version deployed on a Kubernetes cluster in IBM Cloud is available for you to try here](http://ibm.biz/digibank).\nTo test it out, sign up for an account. A process runs periodically to dump randomized transactions and bills for user accounts, so give it a couple of minutes and refresh to see your populated profile.\n\n![Screens](doc/source/images/screens-1.png)\n\n![Screens](doc/source/images/screens-2.png)\n\n## Learning objectives\n\nWhen you've completed this Code Pattern, you will understand how to:\n\n* Break an application down to a set of microservices\n* Create and manage a Kubernetes cluster on IBM Cloud\n* Deploy to a Kubernetes cluster on IBM Cloud\n* Deploy to IBM Cloud Private\n\n## Flow\n\nWhen thinking of business capabilities, our imaginary bank will need the following set of microservices:\n\n1. *Portal:* Loads the UI and takes care of user sessions and relies on all other microservices for core functionality.\n2. *Authentication:* Handles user profile creation, as well as login & logout.\n3. *Accounts:* Handles creation, management, and retrieval of a user’s banking accounts.\n4. *Transactions:* Handles creation and retrieval of transactions made against users' bank accounts.\n5. *Bills:* Handles creation, payment, and retrieval of bills.\n6. *Support:* Handles communication with Watson Assistant to enable a support chat feature.\n\n![Demo architecture](doc/source/images/architecture.png)\n\n## Included components\n\n* [IBM Cloud Kubernetes Service](https://console.bluemix.net/docs/containers/): IBM Cloud Kubernetes Service manages highly available apps inside Docker containers and Kubernetes clusters on the IBM Cloud.\n* [Microservice Builder](https://www.ibm.com/us-en/marketplace/microclimate): Learn, build, run, and manage applications in a microservices framework.\n* [Watson Assistant](https://www.ibm.com/cloud/watson-assistant/): Create a chatbot with a program that conducts a conversation via auditory or textual methods.\n\n## Featured technologies\n\n* [Microservices](https://developer.ibm.com/technologies/microservices/): Collection of fine-grained, loosely coupled services using a lightweight protocol to provide building blocks in modern application composition in the cloud.\n* [Node.js](https://nodejs.org/): An open-source JavaScript run-time environment for executing server-side JavaScript code.\n* [Containers](https://developer.ibm.com/technologies/containers/): Virtual software objects that include all the elements that an app needs to run.\n* [Databases](https://developer.ibm.com/technologies/databases/): Repository for storing and managing collections of data.\n* [Hybrid Cloud](https://developer.ibm.com/depmodels/hybrid/): Enabling customers to draw on the capabilities of public cloud service providers while using private cloud deployment for sensitive applications and data.\n\n## Watch the Video\n\n[![](https://img.youtube.com/vi/1F1EnnMrsZ8/0.jpg)](https://www.youtube.com/watch?v=1F1EnnMrsZ8)\n\n## Setup\n\nYou have multiple options to setup your own instance:\n\n* [Run it locally](#run-locally)\n* [Deploy to IBM Cloud the hard way (manual, multi-stage)](#deploy-to-ibm-cloud-the-hard-way)\n* [Deploy to IBM Cloud Private](#deploy-to-ibm-cloud-private)\n\n## Run Locally\n\n### 1. Clone the repo\n\nClone the `innovate-digital-bank` repository locally. In a terminal, run:\n\n```bash\n$ git clone https://github.com/IBM/innovate-digital-bank.git\n```\n\n### 2. Create an Instance of MongoDB\n\nThis code pattern depends on MongoDB as a session and data store. From the [IBM Cloud catalog](https://cloud.ibm.com/catalog), find **Compose for MongoDB** and click create. Give it a name, choose a region, pick the standard pricing plan and click create.\n\n**Get your mongo connection string. Almost all your microservices need it; keep it safe!**\n\n![kubectl config](doc/source/images/11.png)\n\n### 3. Configure your environment variables\n\nEach of the 7 microservices must have a _**.env**_ file that stores all credentials.\n\nAn example is already provided within each folder. From the directory of each microservice, copy the example file, rename it to _**.env**_, and fill it with the appropriate values.\n\nFor example, from within the **/innovate** folder, navigate into the accounts folder\n\n```bash\n$ cd accounts\n```\n\nNext, copy and rename the _**.env.example**_ folder\n\n```bash\n$ cp .env.example .env\n```\n\nFinally, edit your **.env** folder and add your Mongodb connection string\n\n***Repeat these steps for all microservices. In addition to your mongo URL, most will need the public IP address of your Kubernetes cluster, _You can find that under the overview of your cluster on IBM Cloud_.***\n\n### 4. Configure your environment mode\n\nWhen running the app locally without Kubernetes, the microservices do not run on the NodePorts specified in our helm chart, so we need to point our portal and userbase microservices to the correct ports.\n\nIf you're running on macOS or any linux-based system, run the following in a terminal from the git repo's directory\n\n```bash\n$ export NODE_ENV=development\n```\n\nif you're running on Windows, edit the NODE_ENV attribute in your .env file from within the **/portal** folder and the **/userbase** folder to the following:\n\n```bash\nNODE_ENV=development\n```\n\n### 5. Run\n\nFinally, navigate to each microservice folder, and start it. Make sure you run the 7 microservice in 7 separate terminals.\n\n```bash\n$ npm start\n```\n\nYou can now visit `localhost:3100` to access the portal\n\n## Deploy to IBM Cloud the Hard Way\n\n> NOTE: This guide requires a paid/upgraded account on IBM Cloud. You **cannot** complete the steps with a free or lite account.\n\n1. [Get the tools](#1-get-the-tools)\n2. [Clone the repo](#2-clone-the-repo)\n3. [Login to IBM Cloud](#3-login-to-ibm-cloud)\n4. [Create a cluster](#4-create-a-cluster-)\n5. [Create an instance of MongoDB](#5-create-an-instance-of-mongodb)\n6. [Configure your deploy target](#6-configure-your-deploy-target)\n7. [Configure your environment variables](#7-configure-your-environment-variables)\n8. [Configure kubectl](#8-configure-kubectl)\n9. [Initialize helm](#9-initialize-helm)\n10. [Deploy](#10-deploy)\n\n### 1. Get the tools\n\nYou'll need each of the following pre-requisites:\n\n* The [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/)\n\n* The [IBM Cloud Developer Tools CLI](https://cloud.ibm.com/docs/cli/index.html#overview)\n\n* Thee IBM Cloud plugins: `container-service`, `container-registry`, and `dev`\n\n```bash\n$ ibmcloud plugin install container-service\n$ ibmcloud plugin install container-registry\n$ ibmcloud plugin install dev\n```\n\n### 2. Clone the repo\n\nClone the `innovate-digital-bank` repository locally. In a terminal, run:\n\n```bash\n$ git clone https://github.com/IBM/innovate-digital-bank.git\n```\n\n### 3. Log into IBM Cloud\n\nWe'll need to log into IBM Cloud through both the [console](https://cloud.ibm.com/) and the terminal.\n\n> NOTE: If you need to specify the region you want to deploy in, you can do so by adding the `-a` flag followed by the region URL.\n\n```bash\n$ ibmcloud login\n```\n\n### 4. Create a cluster\n\nFrom the catalog, find **Containers in Kubernetes Clusters** and click create. Choose a region and a cluster type, and create your cluster. Allow it some time to deploy.\n\n![kubectl config](doc/source/images/9.png)\n\n### 5. Create an instance of MongoDB\n\nThis demo depends on MongoDB as a session and data store. From the [catalog](https://cloud.ibm.com/catalog/), find **Compose for MongoDB** and click create. Give it a name, choose a region, pick the standard pricing plan and click create.\n\n**Get your mongo connection string. Almost all your microservices need it; keep it safe!**\n\n![kubectl config](doc/source/images/11.png)\n\n\n### 6. Configure your deploy target\n\nEach of the 7 docker images needs to be pushed to your docker image registry on IBM Cloud. You need to set the correct _**deploy target**_. Depending on the region you've created your cluster in, your URL will be in the following format\n\n```\nregistry.<REGION_ABBREVIATION>.bluemix.net/<YOUR_NAMESPACE>/<YOUR_IMAGE_NAME>\n```\n\nFor example, to deploy the accounts microservice to my docker image registry in the US-South region, my **deploy_target** will be:\n\n```\nregistry.ng.bluemix.net/amalamine/innovate-accounts\n```\n\nIf you need to get your namespace, run:\n\n```bash\n$ ibmcloud cr namespace-list\n```\n\nYou can also add a new namespace by running:\n\n```bash\n$ ibmcloud cr namespace-add <NAME>\n```\n\nFrom the directory of each microservice, replace the deploy target in ***cli-config.yml*** and in ***/chart/innovate-<MICROSERVICE_NAME>/values.yaml*** with the correct one\n\nFor example, from within the **/innovate** folder, navigate into the accounts folder\n\n```bash\n$ cd accounts\n```\n\nNext, edit line 58 of [cli-config.yaml](https://github.com/IBM/innovate-digital-bank/blob/master/accounts/cli-config.yml) file. Replace the ***deploy-image-target*** with the correct value.\n\n```\ndeploy-image-target: \"registry.ng.bluemix.net/amalamine/innovate-accounts\"\n```\n\n![kubectl config](doc/source/images/12.png)\n\nEdit line 6 of the [values.yaml](https://github.com/IBM/innovate-digital-bank/blob/master/accounts/chart/innovate-accounts/values.yaml) file. Replace the ***repository*** with the correct value.\n\n```\nrepository: registry.ng.bluemix.net/amalamine/innovate-accounts\n```\n\n![kubectl config](doc/source/images/13.png)\n\n**Repeat these steps for all 7 microservices.**\n\n### 7. Configure your environment variables\n\nEach of the 7 microservices must have a _**.env**_ file that stores all credentials. An example is already provided within each folder. From the directory of each microservice, copy the example file, rename it to _**.env**_, and fill it with the appropriate values.\n\nFor example, from within the **/innovate** folder, navigate into the accounts folder\n\n```bash\n$ cd accounts\n```\n\nNext, copy and rename the _**.env.example**_ folder\n\n```bash\n$ cp .env.example .env\n```\n\nFinally, edit your .env folder and add your Mongodb connection string\n\n***Repeat these steps for all microservices. In addition to your mongo URL, most will need the public IP address of your Kubernetes cluster, _You can find that under the overview of your cluster on IBM Cloud_.***\n\n### 8. Configure kubectl\n\nRun the following command:\n\n```bash\n$ ibmcloud cs cluster-config <YOUR_CLUSTER_NAME>\n```\n\nThen copy the output and paste it in your terminal\n\n### 9. Initialize helm\n\nIf you dont have helm installed, see the [Helm Documentation](https://docs.helm.sh/using_helm/#install-helm).\n\n```bash\n$ helm init\n```\n\n### 10. Deploy\n\nFinally, navigate to each microservice folder, and run the following command\n\n```bash\n$ ibmcloud dev deploy\n```\n\nOnce done, you'll be able to access the portal on port _30060_ of your cluster's _public IP address_, which you can find under the overview of your cluster on IBM Cloud.\nOr if you are logged in `ibmcloud` cli, you can find your public ip of your worker node by\n\n```bash\n$ ibmcloud cs workers <name-of-cluster>\n```\n\n# Deploy to IBM Cloud Private\n\nIf you have an instance of IBM Cloud Private running, you can follow the steps below to deploy the app. If you'd like to deploy your own instance of ICP, [you can follow this great writeup](https://github.com/IBM/deploy-ibm-cloud-private).\n\n1. [Create a persistent volume](#1-create-a-persistent-volume)\n2. [Create a persistent volume claim](#2-create-a-persistent-volume-claim)\n3. [Create an instance of MongoDB](#3-create-an-instance-of-mongodb)\n4. [Configure your environment variables](#4-configure-your-environment-variables)\n5. [Add your ICP's address to your hosts file](#5-add-your-icps-address-to-your-hosts-file)\n6. [Login to docker](#6-login-to-docker)\n7. [Configure kubectl](#7-configure-kubectl)\n8. [Configure cloudctl](#8-configure-cloudctl)\n9. [Install Helm](#9-install-helm)\n10. [Deploy](#10-deploy)\n\n### 1. Create a persistent volume\n\nThis code pattern depends on MongoDB as a session and data store. From ICP's menu, click on Storage > Create persistent volume. Give it a name and a capacity, choose storage type _**Hostpath**_, and add a _**path parameter**_\n\n[More details here](./creating-pv.md)\n\n### 2. Create a persistent volume claim\n\nFrom ICP's menu, click on **_Storage_** > **_Create Persistent Volume Claim_**. Give it a name and a storage request value.\n\n[More details here](./creating-pvc.md)\n\n### 3. Create an instance of MongoDB\n\nFrom the catalog, choose MongoDB. Give it a **_Name_**, specify the **_Existing Volume Claim Name_**, and give it a **_password_**.\n\n[More details here](./mongo-db.md)\n\n***Get your mongo connection string; Almost all your microservices need it; keep it safe!***\n\nYour connection string will be in the following format:\n\n```\nmongodb://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<DATABASE_NAME>\n```\n\n### 4. Configure your environment variables\n\nEach of the 7 microservices must have a _**.env**_ file. An example is already provided within each folder. From the directory of each microservice, copy the example file, rename it to _**.env**_, and fill it with the appropriate values.\n\nFor example, from within the **/innovate** folder, navigate into the accounts folder\n\n```bash\n$ cd accounts\n```\n\nNext, copy and rename the _**.env.example**_ folder\n\n```bash\n$ cp .env.example .env\n```\n\nFinally, edit your **.env** folder and add your Mongodb connection string\n\n***Repeat those steps for all microservices. In addition to your mongo url, you may the IP address of your ICP.***\n\n### 5. Add your ICP's address to your hosts file\n\nAdd an entry to your /etc/hosts file as follows\n\n```ini\n<YOUR_ICP_IP_ADDRESS> mycluster.icp\n```\n\n### 6. Login to docker\n\nFor Mac users, if you are running ICP locally in VM you would also have to add the cluster info to the insecure registry. To do so, go to the Docker icon in the system tray, select **_Preferences_** > **_Daemon_**, and choose to enable experimental features and add cluster to insecure registries list.\n\n![Docker 1](doc/source/images/docker1.png) ![Docker 2](doc/source/images/docker2.png)\n\n```bash\n$ docker login mycluster.icp:8500\n```\n\n### 7. Configure `kubectl`\n\nFrom your ICP's dashboard, copy the `kubectl` commands under `***REMOVED***` > `configure client`\n\n![kubectl config](doc/source/images/5.png)\n\n### 8. Configure `cloudctl`\n\nIBM Cloud Private provides a custom CLI, similar to `kubectl`, called `cloudctl`. To find the CLI for your ICP version, navigate to **_Menu_** > **_Command Line Tools_** > **_Cloud Private CLI_** and follow instruction to get `cloudctl` installed.\n\n![cloudctl config](doc/source/images/cloudctl1.png)\n![cloudctl config](doc/source/images/cloudctl2.png)\n\nOnce you have `cloudctl` cli installed, log into **ICP**\n\n```bash\n$ cloudctl login -a https://mycluster.icp:8443 -u ***REMOVED*** --skip-ssl-validation\n``` \n\n> NOTE: The default password for the local ICP VM is _***REMOVED***_.\n\n### 9. Install Helm\n\nIf you dont have helm installed, see the [Helm Documentation](https://docs.helm.sh/using_helm/#install-helm).\n\n```bash\n$ helm init\n```\n\n### 10. Deploy\nFinally, navigate to each microservice, and run the following command\n\n```bash\n$ ibmcloud dev deploy\n```\n\nOnce the deployment is successfully completed, you can access the portal on port _30060_ of your _ICP's IP address_.\n\n## (Optional) Adding Support with Watson Assistant\n\nThe *Support* microservice connects to an instance of Watson Assistant on IBM Cloud to simulate a chat with a virtual support agent. *This is an optional step.* You only need to continue if you'd like to enable the *Support* feature in the app.\n\n1. [Create an instance of Watson Assistant](#1-create-an-instance-of-watson-assistant)\n2. [Get your credentials](#2-get-your-credentials)\n3. [Configure your environment variables](#3-configure-your-environment-variables)\n4. [Deploy](#4-deploy)\n\n### 1. Create an instance of Watson Assistant\n\nFrom the [IBM Cloud Catalog](https://cloud.ibm.com/login), choose Watson Assistant, and click *Create*.\n\n### 2. Get your credentials\n\nNavigate to the *Credentials* tab and copy your credentials.\n\n![Watson Conversation](doc/source/images/8.png)\n\n### 3. Configure your environment variables\n\nFrom within the support folder, edit your `.env` to include your newly acquired credentials.\n\n### 4. Deploy\n\nRe-deploy the *Support* microservice, the support feature should now be accessible through the portal.\n\n```bash\n$ ibmcloud dev deploy\n```\n\n## Troubleshooting\n\n1. Trouble with IBM Cloud CLI? See their [Troubleshooting Documentation](https://console.bluemix.net/docs/cli/ts_createapps.html#troubleshoot).\n2. Trouble with IBM Cloud Private? See their [Troubleshooting Documentation](https://www.ibm.com/support/knowledgecenter/en/SS8G7U_18.2.0/com.ibm.app.mgmt.doc/content/trouble_common_deployment_errors.htm)\n3. IBM Cloud Private on local VM not working? Check the ICP version, Vagrant version and VirtualBox version carefully. Update them if necessary. If all else fails, `vagrant destroy` and `vagrant up` again to reset the cluster.\n\n## Learn more\n\n* **Containers Code Patterns**: Enjoyed this Code Pattern? Check out our other [Container Code Patterns](https://developer.ibm.com/technologies/containers/).\n* **IBM Cloud Private Code Patterns**: Enjoyed this Code Pattern? Check out our other [IBM Cloud Private Code Patterns](https://developer.ibm.com/components/cloud-private/)\n* **Kubernetes on IBM Cloud**: Deliver your apps with the combined the power of [Kubernetes and Docker on IBM Cloud](https://www.ibm.com/cloud/container-service)\n\n## Docs\n\nAdditional documentation of all the backend endpoints is available in [DOCS.md](DOCS.md).\n\n## License\n\nThis code pattern is licensed under the Apache Software License, Version 2.  Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the [Developer Certificate of Origin, Version 1.1 (DCO)](https://developercertificate.org/) and the [Apache Software License, Version 2](http://www.apache.org/licenses/LICENSE-2.0.txt).\n\n[Apache Software License (ASL) FAQ](http://www.apache.org/foundation/license-faq.html#WhatDoesItMEAN)\n"
  },
  {
    "path": "accounts/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "accounts/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "accounts/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "accounts/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "accounts/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 3400\n\nEXPOSE 3400\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "accounts/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3400\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3400\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "accounts/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst accounts = require('./mongoose/account');\r\n\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('*', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\napp.post('/api/accounts/create', function (req, res) {\r\n    let number = Math.floor(Math.random() * 900000);\r\n    let balance = 0;\r\n    if (req.body.type === 'current') {\r\n        balance = 5000;\r\n    }\r\n    if (req.body.type === 'credit') {\r\n        balance = 40000;\r\n    }\r\n    var newAccount = {\r\n        uuid: req.body.uuid,\r\n        type: req.body.type,\r\n        currency: req.body.currency,\r\n        balance: balance,\r\n        number: number\r\n    };\r\n    accounts.create(newAccount, function (err) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send(err);\r\n            return;\r\n        }\r\n        console.log(\"Account created\");\r\n        res.status(200).send({'message': 'Done!'});\r\n    });\r\n});\r\n\r\napp.post('/api/accounts/get', function (req, res) {\r\n    accounts.find({'uuid': req.body.uuid}, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': err});\r\n            return;\r\n        }\r\n        res.status(200).send(results);\r\n    });\r\n});\r\n\r\napp.post('/api/accounts/deposit', function (req, res) {\r\n    accounts.find({'number': req.body.number}, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': err});\r\n            return;\r\n        }\r\n        if (results.length === 0) {\r\n            console.log('account not found');\r\n            res.status(500).send({'err': 'account not found'});\r\n            return;\r\n        }\r\n        let amount = Number(results[0].balance) + Number(req.body.amount);\r\n        accounts.findOneAndUpdate({'number': req.body.number}, {'balance': amount}, function (err, results) {\r\n            if (err) {\r\n                console.log(err);\r\n                res.status(500).send({'err': err});\r\n                return;\r\n            }\r\n            res.status(200).send(results);\r\n        });\r\n    });\r\n});\r\n\r\napp.post('/api/accounts/withdraw', function (req, res) {\r\n    accounts.find({'number': req.body.number}, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': err});\r\n            return;\r\n        }\r\n        if (results.length === 0) {\r\n            console.log('account not found');\r\n            res.status(500).send({'err': 'account not found'});\r\n            return;\r\n        }\r\n        let amount = Number(results[0].balance) - Number(req.body.amount);\r\n        accounts.findOneAndUpdate({'number': req.body.number}, {'balance': amount}, function (err, results) {\r\n            if (err) {\r\n                console.log(err);\r\n                res.status(500).send({'err': err});\r\n                return;\r\n            }\r\n            res.status(200).send(results);\r\n        });\r\n    });\r\n});\r\n\r\napp.get('/api/accounts/drop', function (req, res) {\r\n    accounts.collection.drop();\r\n    res.status(200).send({'message': 'Done!'});\r\n});\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "accounts/chart/innovate-accounts/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-accounts\nversion: 1.0.0\n"
  },
  {
    "path": "accounts/chart/innovate-accounts/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "accounts/chart/innovate-accounts/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "accounts/chart/innovate-accounts/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "accounts/chart/innovate-accounts/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-accounts\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3400\n  serviceNodePort: 30120\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "accounts/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-accounts-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-accounts-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"3400:3400\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5862:5862\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-accounts-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-accounts-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-accounts\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-accounts\"\n"
  },
  {
    "path": "accounts/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "accounts/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-accounts\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "accounts/mongoose/account.js",
    "content": "const mongoose = require('mongoose');\n\nvar Schema = mongoose.Schema;\nvar Account = new Schema({\n    uuid: String,\n    type: String,\n    currency: String,\n    balance: Number,\n    number: Number\n});\n\nmodule.exports = mongoose.model('Account', Account, \"accounts\");\n"
  },
  {
    "path": "accounts/package.json",
    "content": "{\n  \"name\": \"innovate-accounts\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"jslint\": \"^0.12.0\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "accounts/server.js",
    "content": "'use strict';\n\nconst mongoose = require('mongoose');\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 3400;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\n\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\n    connection.onOpen();\n    server.listen(port, function () {\n        console.log('Server running on port: %d', port);\n    });\n});\n"
  },
  {
    "path": "authentication/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "authentication/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "authentication/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "authentication/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "authentication/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 3200\n\nEXPOSE 3200\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "authentication/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3200\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3200\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "authentication/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst users = require('./mongoose/user');\r\nconst uuidv4 = require('uuid/v4');\r\n\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('/', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\napp.post('/api/user/create', function (req, res) {\r\n    findUser({'email': req.body.email}, function (err, user) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send('Something went wrong. Try again in a few seconds, or contact support.');\r\n            return;\r\n        }\r\n        if (user) {\r\n            res.status(500).send({'err': 'Seems like you already have an account with us. Please log in instead, or contact support to recover regain to your account.'});\r\n            return;\r\n        }\r\n        var uuid = uuidv4();\r\n        var newUser = {\r\n            uuid: uuid,\r\n            name: req.body.name,\r\n            email: req.body.email,\r\n            phone: req.body.phone,\r\n            gender: req.body.gender,\r\n            dob: req.body.dob,\r\n            eid: req.body.eid,\r\n            password: req.body.password\r\n        };\r\n        users.create(newUser, function (err) {\r\n            if (err) {\r\n                console.log(err);\r\n                res.status(500).send('Something went wrong. Try again in a few seconds, or contact support.');\r\n                return;\r\n            }\r\n            console.log(\"User created\");\r\n            res.status(200).send(newUser);\r\n        });\r\n    });\r\n});\r\n\r\napp.post('/api/user/authenticate', function (req, res) {\r\n    findUser({'email': req.body.email, 'password': req.body.password}, function (err, user) {\r\n        if (err) {\r\n          console.log(err);\r\n          res.status(500).send({'err': 'Something went wrong. Try again in a few seconds, or contact support.'});\r\n          return;\r\n        }\r\n        if (!user) {\r\n          res.status(500).send({'err': `Your username & password are incorrect. Try again, or contact support to recover lost login details. `});\r\n          return;\r\n        }\r\n        res.status(200).send(user);\r\n    });\r\n});\r\n\r\napp.get('/api/user/get', function(req, res) {\r\n    findUser({}, function (err, users) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': 'Something went wrong. Try again in a few seconds, or contact support.'});\r\n            return;\r\n        }\r\n        if (!users) {\r\n            res.status(500).send({'err': 'No Users Found'});\r\n            return;\r\n        }\r\n        res.status(200).send(users);\r\n    });\r\n});\r\n\r\nfunction findUser (criteria, callback){\r\n    users.find(criteria, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            callback(err);\r\n        }\r\n        if (Object.keys(criteria).length > 0) {\r\n          results = results[0];\r\n        }\r\n        callback(null, results);\r\n    });\r\n};\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "authentication/chart/innovate-authentication/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-authentication\nversion: 1.0.0\n"
  },
  {
    "path": "authentication/chart/innovate-authentication/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "authentication/chart/innovate-authentication/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "authentication/chart/innovate-authentication/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "authentication/chart/innovate-authentication/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-authentication\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3200\n  serviceNodePort: 30100\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "authentication/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-authentication-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-authentication-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"3200:3200\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5860:5860\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-authentication-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-authentication-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-authentication\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-authentication\"\n"
  },
  {
    "path": "authentication/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "authentication/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-authentication\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "authentication/mongoose/user.js",
    "content": "const mongoose = require('mongoose');\n\nvar Schema = mongoose.Schema;\nvar User = new Schema({\n    uuid: String,\n    name: String,\n    email: String,\n    phone: String,\n    gender: String,\n    dob: String,\n    eid: String,\n    password: String\n});\n\nmodule.exports = mongoose.model('User', User, \"users\");\n"
  },
  {
    "path": "authentication/package.json",
    "content": "{\n  \"name\": \"innovate-authentication\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "authentication/server.js",
    "content": "'use strict';\n\nconst mongoose = require('mongoose');\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 3200;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\n\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\n    connection.onOpen();\n    server.listen(port, function () {\n        console.log('Server running on port: %d', port);\n    });\n});\n"
  },
  {
    "path": "bills/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "bills/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "bills/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "bills/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "bills/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 3800\n\nEXPOSE 3800\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "bills/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3800\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3800\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "bills/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst bills = require('./mongoose/bill');\r\n\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('*', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\napp.post('/api/bills/create', function (req, res) {\r\n    var newBill = {\r\n        uuid: req.body.uuid,\r\n        category: req.body.category,\r\n        entity: req.body.entity,\r\n        account_no: req.body.account_no,\r\n        amount: req.body.amount,\r\n        date: req.body.date\r\n    };\r\n    bills.update({'category': req.body.category}, newBill, {upsert: true}, function (err) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send(err);\r\n            return;\r\n        }\r\n        console.log(\"Bill created\");\r\n        res.status(200).send({'message': 'Done!'});\r\n    });\r\n});\r\n\r\napp.post('/api/bills/get', function (req, res) {\r\n    bills.find({'uuid': req.body.uuid}, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': err});\r\n            return;\r\n        }\r\n        res.status(200).send(results);\r\n    });\r\n});\r\n\r\napp.get('/api/bills/drop', function (req, res) {\r\n    bills.collection.drop();\r\n    res.status(200).send({'message': 'Done!'});\r\n});\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "bills/chart/innovate-bills/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-bills\nversion: 1.0.0\n"
  },
  {
    "path": "bills/chart/innovate-bills/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "bills/chart/innovate-bills/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "bills/chart/innovate-bills/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "bills/chart/innovate-bills/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-bills\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3800\n  serviceNodePort: 30160\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "bills/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-bills-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-bills-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"3800:3800\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5866:5866\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-bills-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-bills-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-bills\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-bills\"\n"
  },
  {
    "path": "bills/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "bills/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-bills\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "bills/mongoose/bill.js",
    "content": "const mongoose = require('mongoose');\n\nvar Schema = mongoose.Schema;\nvar Bill = new Schema({\n    uuid: String,\n    category: String,\n    entity: String,\n    account_no: String,\n    amount: Number,\n    currency: String,\n    date: String\n});\n\nmodule.exports = mongoose.model('Bill', Bill, \"bills\");\n"
  },
  {
    "path": "bills/package.json",
    "content": "{\n  \"name\": \"innovate-bills\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "bills/server.js",
    "content": "'use strict';\n\nconst mongoose = require('mongoose');\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 3800;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\n\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\n    connection.onOpen();\n    server.listen(port, function () {\n        console.log('Server running on port: %d', port);\n    });\n});\n"
  },
  {
    "path": "chart/innovate-bank/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank\nname: innovate-bank\nversion: 2.0.0\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/Chart.yaml",
    "content": "name: mongodb\nversion: 1.0.0\nappVersion: 3.7.3\ndescription: NoSQL document-oriented database that stores JSON-like documents with dynamic schemas, simplifying the integration of data in content-driven applications.\nkeywords:\n- mongodb\n- database\n- nosql\nhome: https://mongodb.org\nicon: https://bitnami.com/assets/stacks/mongodb/img/mongodb-stack-220x234.png\nsources:\n- https://github.com/bitnami/bitnami-docker-mongodb\nmaintainers:\n- name: Bitnami\n  email: containers@bitnami.com\nengine: gotpl\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/_helpers.tpl",
    "content": "{{/* vim: set filetype=mustache: */}}\n{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"mongodb.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n\n{{/*\nCreate a default fully qualified app name.\nWe truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).\n*/}}\n{{- define \"mongodb.fullname\" -}}\n{{- $name := default .Chart.Name .Values.nameOverride -}}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: {{ template \"mongodb.fullname\" . }}\n  labels:\n    app: {{ template \"mongodb.fullname\" . }}\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version }}\"\n    release: \"{{ .Release.Name }}\"\n    heritage: \"{{ .Release.Service }}\"\nspec:\n  template:\n    metadata:\n      labels:\n        app: {{ template \"mongodb.fullname\" . }}\n    spec:\n      containers:\n      - name: {{ template \"mongodb.fullname\" . }}\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        env:\n        - name: MONGODB_ROOT_PASSWORD\n          valueFrom:\n            secretKeyRef:\n              name: {{ template \"mongodb.fullname\" . }}\n              key: mongodb-root-password\n        - name: MONGODB_USERNAME\n          value: {{ default \"\" .Values.mongodbUsername | quote }}\n        - name: MONGODB_PASSWORD\n          valueFrom:\n            secretKeyRef:\n              name: {{ template \"mongodb.fullname\" . }}\n              key: mongodb-password\n        - name: MONGODB_DATABASE\n          value: {{ default \"\" .Values.mongodbDatabase | quote }}\n        ports:\n        - name: mongodb\n          containerPort: 27017\n        livenessProbe:\n          exec:\n            command:\n            - mongo\n            - --eval\n            - \"db.***REMOVED***Command('ping')\"\n          initialDelaySeconds: 30\n          timeoutSeconds: 5\n        readinessProbe:\n          exec:\n            command:\n            - mongo\n            - --eval\n            - \"db.***REMOVED***Command('ping')\"\n          initialDelaySeconds: 5\n          timeoutSeconds: 1\n        volumeMounts:\n        - name: data\n          mountPath: /data/mongo\n        resources:\n{{ toYaml .Values.resources | indent 10 }}\n      volumes:\n      - name: data\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          claimName: {{ template \"mongodb.fullname\" . }}\n      {{- else }}\n        emptyDir: {}\n      {{- end -}}\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/pv.yaml",
    "content": "apiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: {{ template \"mongodb.fullname\" . }}\nspec:\n  capacity:\n    storage: {{ .Values.persistence.size }}\n  accessModes:\n  - {{ .Values.persistence.accessMode }}\n  hostPath:\n    path: {{ .Values.persistence.path }}\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/pvc.yaml",
    "content": "kind: PersistentVolumeClaim\napiVersion: v1\nmetadata:\n  name: {{ template \"mongodb.fullname\" . }}\n  labels:\n    billingType: {{ .Values.persistence.billingType }}\nspec:\n  accessModes:\n    - {{ .Values.persistence.accessMode }}\n  resources:\n    requests:\n      storage: {{ .Values.persistence.claimSize }}\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/secrets.yaml",
    "content": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ template \"mongodb.fullname\" . }}\n  labels:\n    app: {{ template \"mongodb.fullname\" . }}\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version }}\"\n    release: \"{{ .Release.Name }}\"\n    heritage: \"{{ .Release.Service }}\"\ntype: Opaque\ndata:\n  {{ if .Values.mongodbRootPassword }}\n  mongodb-root-password:  {{ .Values.mongodbRootPassword | b64enc | quote }}\n  {{ else }}\n  mongodb-root-password: {{ randAlphaNum 10 | b64enc | quote }}\n  {{ end }}\n  {{ if .Values.mongodbPassword }}\n  mongodb-password:  {{ .Values.mongodbPassword | b64enc | quote }}\n  {{ else }}\n  mongodb-password: {{ randAlphaNum 10 | b64enc | quote }}\n  {{ end }}"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"mongodb.fullname\" . }}\n  labels:\n    app: {{ template \"mongodb.fullname\" . }}\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version }}\"\n    release: \"{{ .Release.Name }}\"\n    heritage: \"{{ .Release.Service }}\"\nspec:\n  type: {{ .Values.serviceType }}\n  ports:\n  - name: mongodb\n    port: 27017\n    targetPort: mongodb\n    nodePort: 30443\n  selector:\n    app: {{ template \"mongodb.fullname\" . }}\n"
  },
  {
    "path": "chart/innovate-bank/charts/mongodb/values.yaml",
    "content": "image:\n  registry: docker.io\n  repository: bitnami/mongodb\n  tag: 3.7.3\n  pullPolicy: IfNotPresent\nmongodbRootPassword: mongo\nmongodbUsername: mongo\nmongodbPassword: ***REMOVED***\nmongodbDatabase: ***REMOVED***\nserviceType: NodePort\npersistence:\n  enabled: true\n  accessMode: ReadWriteMany\n  size: 5Gi\n  claimSize: 1Gi\n  storageClass: ibmc-file-bronze\n  billingType: hourly\n  path: /innovate\nresources:\n  requests:\n    memory: 512Mi\n    cpu: 200m\n"
  },
  {
    "path": "chart/innovate-bank/templates/_helpers.tpl",
    "content": "{{/* vim: set filetype=mustache: */}}\n{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n\n{{/*\nCreate a default fully qualified app name.\nWe truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).\n*/}}\n{{- define \"fullname\" -}}\n{{- $name := default .Chart.Name .Values.nameOverride -}}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n"
  },
  {
    "path": "chart/innovate-bank/templates/configmap.yaml",
    "content": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: \"{{  .Chart.Name }}-configmap\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\ndata:\n  mongoUrl: \"{{ .Values.config.mongoUrl }}\"\n  basePath: \"{{ .Values.config.basePath }}\"\n  sessionSecret: \"{{ .Values.config.sessionSecret }}\"\n  nodeEnv: \"{{ .Values.config.nodeEnv }}\"\n  signupEndpoint: \"/api/user/create\"\n  loginEndpoint: \"/api/user/authenticate\"\n  getUsersEndpoint: \"/api/user/get\"\n  getBillsEndpoint: \"/api/bills/get\"\n  upsertBillEndpoint: \"/api/bills/create\"\n  dropBillsEndpoint: \"/api/bills/drop\"\n  createAccountEndpoint: \"/api/accounts/create\"\n  getAccountsEndpoint: \"/api/accounts/get\"\n  accountWithdrawEndpoint: \"/api/accounts/withdraw\"\n  accountDepositEndpoint: \"/api/accounts/deposit\"\n  dropAccountsEndpoint: \"/api/accounts/drop\"\n  createTransactionEndpoint: \"/api/transactions/create\"\n  getTransactionsEndpoint: \"/api/transactions/get\"\n  dropTransactionsEndpoint: \"/api/transactions/drop\"\n  chatEndpoint: \"/api/message\"\n"
  },
  {
    "path": "chart/innovate-bank/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      imagePullSecrets:\n        - name: {{ .Values.image.pullSecret }}\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: MONGO_URL\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: mongoUrl\n          - name: BASE_PATH\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: basePath\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n          - name: SESSION_SECRET\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: sessionSecret\n          - name: NODE_ENV\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: nodeEnv\n          - name: SIGNUP_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: signupEndpoint\n          - name: LOGIN_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: loginEndpoint\n          - name: GET_USERS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: getUsersEndpoint\n          - name: GET_BILLS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: getBillsEndpoint\n          - name: UPSERT_BILL_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: upsertBillEndpoint\n          - name: DROP_BILLS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: dropBillsEndpoint\n          - name: CREATE_ACCOUNT_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: createAccountEndpoint\n          - name: GET_ACCOUNTS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: getAccountsEndpoint\n          - name: ACCOUNT_WITHDRAW_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: accountWithdrawEndpoint\n          - name: ACCOUNT_DEPOSIT_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: accountDepositEndpoint\n          - name: DROP_ACCOUNTS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: dropAccountsEndpoint\n          - name: CREATE_TRANSACTION_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: createTransactionEndpoint\n          - name: GET_TRANSACTIONS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: getTransactionsEndpoint\n          - name: DROP_TRANSACTIONS_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: dropTransactionsEndpoint\n          - name: CHAT_ENDPOINT\n            valueFrom:\n              configMapKeyRef:\n                name: \"{{  .Chart.Name }}-configmap\"\n                key: chatEndpoint\n          - name: CONVERSATION_BINDING\n            valueFrom:\n              secretKeyRef:\n                name: \"binding-innovate-conversation-service\"\n                key: binding\n"
  },
  {
    "path": "chart/innovate-bank/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "chart/innovate-bank/templates/ingress.yaml",
    "content": "{{- if .Values.ingress.enabled -}}\n{{- $serviceName := include \"fullname\" . -}}\n{{- $servicePort := .Values.service.externalPort -}}\napiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n  name: {{ template \"fullname\" . }}\n  labels:\n    app: {{ template \"name\" . }}\n    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\n    release: {{ .Release.Name }}\n    heritage: {{ .Release.Service }}\n  annotations:\n    {{- range $key, $value := .Values.ingress.annotations }}\n      {{ $key }}: {{ $value | quote }}\n    {{- end }}\nspec:\n  rules:\n    {{- range $host := .Values.ingress.hosts }}\n    - host: {{ $host }}\n      http:\n        paths:\n          - path: /\n            backend:\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $servicePort }}\n    {{- end -}}\n  {{- if .Values.ingress.tls }}\n  tls:\n{{ toYaml .Values.ingress.tls | indent 4 }}\n  {{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "chart/innovate-bank/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - name: portal\n    port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  - name: authentication\n    port: {{ .Values.authentication.servicePort }}\n    nodePort: {{ .Values.authentication.serviceNodePort }}\n  - name: accounts\n    port: {{ .Values.accounts.servicePort }}\n    nodePort: {{ .Values.accounts.serviceNodePort }}\n  - name: transactions\n    port: {{ .Values.transactions.servicePort }}\n    nodePort: {{ .Values.transactions.serviceNodePort }}\n  - name: bills\n    port: {{ .Values.bills.servicePort }}\n    nodePort: {{ .Values.bills.serviceNodePort }}\n  - name: support\n    port: {{ .Values.support.servicePort }}\n    nodePort: {{ .Values.support.serviceNodePort }}\n  - name: userbase\n    port: {{ .Values.userbase.servicePort }}\n    nodePort: {{ .Values.userbase.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "chart/innovate-bank/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: innovate-bank\n  tag: 1\n  pullSecret: regsecret\n  pullPolicy: IfNotPresent\n  resources:\n    requests:\n      cpu: 300m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3100\n  serviceNodePort: 30200\nauthentication:\n  servicePort: 3200\n  serviceNodePort: 30100\naccounts:\n  servicePort: 3400\n  serviceNodePort: 30120\ntransactions:\n  servicePort: 3600\n  serviceNodePort: 30140\nbills:\n  servicePort: 3800\n  serviceNodePort: 30160\nsupport:\n  servicePort: 4000\n  serviceNodePort: 30180\nuserbase:\n  servicePort: 4100\n  serviceNodePort: 30050\ningress:\n  enabled: false\n  # Used to create an Ingress record.\n  hosts:\n    - chart-example.local\n  annotations:\n    # kubernetes.io/ingress.class: nginx\n    # kubernetes.io/tls-acme: \"true\"\n  tls:\n    # Secrets must be manually created in the namespace.\n    # - secretName: chart-example-tls\n    #   hosts:\n    #     - chart-example.local\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nconfig:\n  mongoUrl: placeholder\n  basePath: placeholder\n  sessionSecret: \"***REMOVED***\"\n  nodeEnv: production\nservices:\n"
  },
  {
    "path": "cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-bank-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-bank-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map: \"3100:3100,3200:3200\"\n\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug: \"5858:5858,5860:5860\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-bank-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-bank-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-bank\"\ndeploy-target: \"container\"\ndeploy-image-target: \"registry.eu-de.bluemix.net/amalamine/innovate-bank\"\n"
  },
  {
    "path": "creating-pv.md",
    "content": "# Creating Persistent Volume in ICP\n\nWe will be using a persisten volume to deploy mongo db for our application.\n\nTo create a Persisten Volume \n1. Navigate to Menu > Platform > Storage\n![console](doc/source/images/pv1.png) \n![menu](doc/source/images/pv2.png)\n\n2. Select `Create Persistent Volume` \n![Persistent Volume](doc/source/images/pv3.png)\n\n3. In General set name, capacity, access type, storage type.\nFor our use case we will create a persisten volume with name `mongo-pv`, `5 gb` capacity with `Read write many` access mode and storage type `Host Path`\n![setting 1](doc/source/images/pv4.png)\n![setting 2](doc/source/images/pv5.png)\n\n4. In Parameter set `key` to `/renovate`\n![setting 3](doc/source/images/pv6.png)\n\n5. Click create."
  },
  {
    "path": "creating-pvc.md",
    "content": "# Create Persistent Volume Claim in ICP\n\nTo create persistent volume claim in IBM Cloud Private\n\n1. After you have created a persistent volume, click on the `Persistent Volume Claim` tab.\n![pvc](doc/source/images/pvc1.png)\n\n2. Click on `Create PersistentVolumeClaim` button\n![click](doc/source/images/pvc2.png)\n\n3. Select a name, storage request and access mode. \nFor our case we are going with `mongo-pvc`, `1 Gb` and `Read write many`\n![setting 1](doc/source/images/pvc3.png)\n![setting 2](doc/source/images/pvc4.png)\n\n4. Click Create."
  },
  {
    "path": "idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "mongo-db.md",
    "content": "# Create Mongo-DB deployment in ICP\n\nTo create a mongo db deployment in Ibm Cloud Private \n1. Navigate to catalog in the top right corner.\n\n2. Search for `mongo` in the catalog. Select mongodb\n![mongo](doc/source/images/mongo1.png)\n\n3. Move to configuration tab and give the release a name. \n![mongo](doc/source/images/mongo2.png)\n\n4. Expand `All Parameters`\n\n5. Check `Enable Persistance for this deployment`. In **Data Volume Configuration** put the name of the **Persistent Volume Claim** created in the last section. In our case its called `mongo-pvc`. Set the size of the claim to `5 Gb`\n![mongo](doc/source/images/mongo3.png)\n\n6. In **MongoDB Configuration** set a username, password, database name and mongo connect command.\n![mongo](doc/source/images/mongo4.png)\n\n7. Click Install. "
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"innovate\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node support/server.js & node accounts/server.js & node authentication/server.js & node bills/server.js & node transactions/server.js & node userbase/server.js & node portal/server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"sudo ibmcloud dev build --debug\",\n    \"test\": \"sudo ibmcloud dev build --debug\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"connect-mongo\": \"^2.0.1\",\n    \"cookie-parser\": \"^1.4.3\",\n    \"date_format\": \"^0.1.1\",\n    \"dateformat\": \"^3.0.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"express-session\": \"^1.15.6\",\n    \"ip\": \"^1.1.5\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"request-promise\": \"^4.2.2\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "portal/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js"
  },
  {
    "path": "portal/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "portal/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\nnode_modules_linux/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\nbuildContext.tar\n"
  },
  {
    "path": "portal/.ibm-project",
    "content": "{\"build-release-ready\":false,\"build-debug-ready\":true,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "portal/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 3000\n\nEXPOSE 3000\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "portal/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3000\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3000\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "portal/chart/innovate-portal/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-portal\nversion: 1.0.0\n"
  },
  {
    "path": "portal/chart/innovate-portal/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "portal/chart/innovate-portal/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "portal/chart/innovate-portal/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "portal/chart/innovate-portal/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-portal\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3100\n  serviceNodePort: 30060\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "portal/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-portal-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-portal-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"3000:3000\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5858:5858\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-portal-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-portal-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-portal\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-portal\"\n"
  },
  {
    "path": "portal/config.js",
    "content": "module.exports = {\n  development: {\n    ports: {\n      portal: 3100,\n      authentication: 3200,\n      accounts: 3400,\n      transactions: 3600,\n      bills: 3800,\n      support: 4000,\n      userbase: 4100\n    }\n  },\n  production: {\n    ports: {\n      portal: 30200,\n      authentication: 30100,\n      accounts: 30120,\n      transactions: 30140,\n      bills: 30160,\n      support: 30180,\n      userbase: 30050\n    }\n  }\n};\n"
  },
  {
    "path": "portal/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "portal/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-portal\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "portal/package.json",
    "content": "{\n  \"name\": \"innovate\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"test\": \"npm run test:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"connect-mongo\": \"^2.0.1\",\n    \"cookie-parser\": \"^1.4.3\",\n    \"date_format\": \"^0.1.1\",\n    \"dateformat\": \"^3.0.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"express-session\": \"^1.15.6\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"request-promise\": \"^4.2.2\",\n    \"strong-supervisor\": \"^6.2.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "portal/public/accounts.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\n\t\t<header class=\"bar\">\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"overview.html\">Spending</a></li>\n\t\t\t\t\t\t<li><a href=\"bills.html\">Bills</a></li>\n\t\t\t\t\t\t<li><a href=\"accounts.html\">Accounts</a></li>\n\t\t\t\t\t\t<li><a href=\"chat.html\">Support</a></li>\n\t\t\t\t\t\t<li><a href=\"/endpoints/logout\">Logout</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t</header>\n\n\t\t<section class=\"section-spending\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Accounts</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<h3><span class=\"small\">AED </span><span id='js-balance'></span></h3>\n\t\t\t\t<p>Total balance</p>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<section class=\"section-bill-list\">\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/account-types/current.png\" alt=\"logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Current</h3>\n\t\t\t\t\t<p><span id=\"current_label\"></span><span id=\"current_number\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"current_balance\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"current_button\" class=\"btn btn-ghost\" href=\"\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/account-types/savings.png\" alt=\"logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Savings</h3>\n\t\t\t\t\t<p><span id=\"savings_label\"></span><span id=\"savings_number\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"savings_balance\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"savings_button\" class=\"btn btn-ghost\" href=\"\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/account-types/credit.png\" alt=\"Innovatee logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Credit</h3>\n\t\t\t\t\t<p><span id=\"credit_label\"></span><span id=\"credit_number\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"credit_balance\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"credit_button\" class=\"btn btn-ghost\" href=\"\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/account-types/prepaid.png\" alt=\"Innovatee logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Prepaid</h3>\n\t\t\t\t\t<p><span id=\"prepaid_label\"></span><span id=\"prepaid_number\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"prepaid_balance\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"prepaid_button\" class=\"btn btn-ghost\" href=\"\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<!---\n\t\tActivation Popups\n\t\t--->\n\n\t\t<div id=\"confirm-popup-current\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to activate your current account. This account is free to activate and maintain. No minimum balance required.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"current_confirm_button\" class=\"btn btn-full\" href=\"/endpoints/accounts/activate?type=current\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div id=\"confirm-popup-current\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to activate your current account. This account is free to activate and maintain. No minimum balance required.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"current_confirm_button\" class=\"btn btn-full\" href=\"\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div id=\"confirm-popup-savings\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to activate your savings account. This account is free to activate and maintain. A minimum balance of 3000 AED is required.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"savings_confirm_button\" class=\"btn btn-full\" href=\"/endpoints/accounts/activate?type=savings\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div id=\"confirm-popup-credit\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to activate a credit card. This credit card is free of charge. An interest rate of 3.45% applies.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"credit_confirm_button\" class=\"btn btn-full\" href=\"/endpoints/accounts/activate?type=credit\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div id=\"confirm-popup-prepaid\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to activate a prepaid card. This card is free to activate and maintain. No minimum balance required. Withdrawal and deposit charges apply.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"prepaid_confirm_button\" class=\"btn btn-full\" href=\"/endpoints/accounts/activate?type=prepaid\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<!---\n\t\tPayment Popups\n\t\t--->\n\t\t\n\t\t<div id=\"confirm-popup-transfer\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed with transfer?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<form method=\"post\" action=\"endpoints/accounts/transfer\" class=\"sign-up-form\">\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\t<div class=\"row left-align\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"amount\">I'm about to transfer</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"number\" name=\"amount\" id=\"amount\" placeholder=\"Amount\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row left-align\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>From my account no.</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<select name=\"from\" id=\"from\">\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row left-align\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>To my account no.</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<select name=\"to\" id=\"to\">\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<input type=\"submit\" value=\"Go ahead\">\n\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!---\n\t\tConfirmation popups\n\t\t--->\n\t\t\n\t\t<div id=\"activated\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Done!</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tAwesome! Your account was successfully activated.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-android-checkmark-circle icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"success\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Done!</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tTransfer, done. Your transaction was successfully completed.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-android-checkmark-circle icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"failure\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYour transaction could not be completed. Please try again or contact support.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-ios-close icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"res/js/accounts.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/bills.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\n\t\t<header class=\"bar\">\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"overview.html\">Spending</a></li>\n\t\t\t\t\t\t<li><a href=\"bills.html\">Bills</a></li>\n\t\t\t\t\t\t<li><a href=\"accounts.html\">Accounts</a></li>\n\t\t\t\t\t\t<li><a href=\"chat.html\">Support</a></li>\n\t\t\t\t\t\t<li><a href=\"/endpoints/logout\">Logout</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t</header>\n\n\t\t<section class=\"section-spending\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Bills</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<h3><span id=\"js-total\"></span></h3>\n\t\t\t\t<p>Due this month</p>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<section class=\"section-bill-list\">\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/sp/dewa.png\" alt=\"logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Water and Electricity</h3>\n\t\t\t\t\t<p><span id=\"utilities_entity\"></span><span id=\"utilities_account\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"utilities_amount\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"utilities_pay_button\" class=\"btn btn-ghost\" href=\"#confirm-popup-utiltities\">Pay</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/sp/etisalat.png\" alt=\"logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Home Entertainment</h3>\n\t\t\t\t\t<p><span id=\"home_entertainment_entity\"></span><span id=\"home_entertainment_account\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"home_entertainment_amount\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"home_entertainment_pay_button\" class=\"btn btn-ghost\" href=\"#confirm-popup-home-entertainment\">Pay</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/sp/du.png\" alt=\"Innovatee logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Mobile Phone</h3>\n\t\t\t\t\t<p><span id=\"mobile_phone_entity\"></span><span id=\"mobile_phone_account\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"mobile_phone_amount\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"mobile_phone_pay_button\" class=\"btn btn-ghost\" href=\"#confirm-popup-mobile-phone\">Pay</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row bill\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<img src=\"res/img/sp/innovate.png\" alt=\"Innovatee logo\" class=\"service-provider-logo\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-2-of-5\">\n\t\t\t\t\t<h3>Credit Card</h3>\n\t\t\t\t\t<p><span id=\"credit_card_entity\"></span><span id=\"credit_card_account\"></span></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3><span id=\"credit_card_amount\"></span></h3>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<a id=\"credit_card_pay_button\" class=\"btn btn-ghost\" href=\"#confirm-popup-credit-card\">Pay</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<!---\n\t\tConfirmation popups\n\t\t--->\n\n\t\t<div id=\"confirm-popup-utiltities\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed with payment?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to pay <span id=\"utilities_bill_amount\"></span> towards your <span id=\"utilities_bill_entity\"></span><span id=\"utilities_bill_account\"></span>.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"utilities_confirm_button\" class=\"btn btn-full\" href=\"\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"confirm-popup-home-entertainment\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed with payment?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to pay <span id=\"home_entertainment_bill_amount\"></span> towards your <span id=\"home_entertainment_bill_entity\"></span><span id=\"home_entertainment_bill_account\"></span>.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"home_entertainment_confirm_button\" class=\"btn btn-full\" href=\"t\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"confirm-popup-mobile-phone\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed with payment?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to pay <span id=\"mobile_phone_bill_amount\"></span> towards your <span id=\"mobile_phone_bill_entity\"></span><span id=\"mobile_phone_bill_account\"></span>.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"mobile_phone_confirm_button\" class=\"btn btn-full\" href=\"/endpoints/bills/pay?category=mobile_phone\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"confirm-popup-credit-card\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Proceed with payment?</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYou're about to pay <span id=\"credit_card_bill_amount\"></span> towards your <span id=\"credit_crd_bill_entity\"></span><span id=\"credit_card_bill_account\"></span>.\n\t\t\t\t</div>\n\t\t\t\t<a id=\"credit_card_confirm_button\" class=\"btn btn-full\" href=\"\">Go ahead</a>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!---\n\t\tPayment popups\n\t\t--->\n\n\t\t<div id=\"success\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Done!</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tBill, down. Your payment was successfully completed.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-android-checkmark-circle icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"failure\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYour payment could not be completed. Please try again or contact support.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-ios-close icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"res/js/bills.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/chat.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/chat.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n<body>\n\t<header class=\"bar\">\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"overview.html\">Spending</a></li>\n\t\t\t\t\t\t<li><a href=\"bills.html\">Bills</a></li>\n\t\t\t\t\t\t<li><a href=\"accounts.html\">Accounts</a></li>\n\t\t\t\t\t\t<li><a href=\"chat.html\">Support</a></li>\n\t\t\t\t\t\t<li><a href=\"/endpoints/logout\">Logout</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t</header>\n\n\n  <div id=\"contentParent\" class=\"responsive-columns-wrapper\">\n    <div id=\"chat-column-holder\" class=\"responsive-column content-column\">\n      <div class=\"chat-column\">\n        <div id=\"scrollingChat\"></div>\n        <label for=\"textInput\" class=\"inputOutline\">\n          <input id=\"textInput\" class=\"input responsive-column\"\n            placeholder=\"Type something\" type=\"text\"\n            onkeydown=\"ConversationPanel.inputKeyDown(event, this)\">\n        </label>\n      </div>\n    </div>\n    <div id=\"payload-column\" class=\"fixed-column content-column\">\n      <div id=\"payload-initial-message\">\n        Type something to see the output\n      </div>\n      <div id=\"payload-request\" class=\"payload\"></div>\n      <div id=\"payload-response\" class=\"payload\"></div>\n    </div>\n  </div>\n\n\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n  <script src=\"res/js/common.js\"></script>\n  <script src=\"res/js/api.js\"></script>\n  <script src=\"res/js/conversation.js\"></script>\n  <script src=\"res/js/payload.js\"></script>\n  <script src=\"res/js/global.js\"></script>\n\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "portal/public/index.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\n\t\t<header>\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"#\">Home</a></li>\n\t\t\t\t\t\t<li><a href=\"#js-section-features\">Features</a></li>\n\t\t\t\t\t\t<li><a href=\"login.html\">Log In</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t\t<div class=\"hero-text-box\">\n\t\t\t\t<h1>This is banking like never before. We’re building the best digital bank on the planet and we want you on board.</h1>\n\t\t\t\t<a class=\"btn btn-full\" href=\"signup.html\">Start banking</a>\n\t\t\t\t<a class=\"btn btn-ghost\" href=\"#js-section-features\">Show me more</a>\n\t\t\t</div>\n\t\t</header>\n\t\t<section id=\"js-section-features\" class=\"section-features\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>The bank of the future</h2>\n\t\t\t\t<p class=\"long-copy\">\n\t\t\t\t\tBuilt for your smartphone, this is banking like never before. One that updates your balance instantly, sends intelligent notifications, and is actually easy to use.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-4 box\">\n\t\t\t\t\t<i class=\"ion-paper-airplane icon-big\"></i>\n\t\t\t\t\t<h3>Instant notifications</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tInnovate sends you a notification whenever you make a payment.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-4 box\">\n\t\t\t\t\t<i class=\"ion-android-time icon-big\"></i>\n\t\t\t\t\t<h3>Fast, friendly support</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tInnovate provides world-class support through in-app chat, with an average response time of under ten minutes.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-4 box\">\n\t\t\t\t\t<i class=\"ion-cash icon-big\"></i>\n\t\t\t\t\t<h3>Budget breakdowns</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tWe automatically categorise your transactions to help you keep track of your spending.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-4 box\">\n\t\t\t\t\t<i class=\"ion-earth icon-big\"></i>\n\t\t\t\t\t<h3>Fee-free travel abroad</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tPurchases with your Innovate card are free, both in country and abroad.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<section class=\"section-form\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Help us build the kind of bank you want to use</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<form method=\"post\" action=\"#\" class=\"contact-form\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"name\">Name</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"name\" placeholder=\"Your name\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"email\">Email</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"email\" name=\"email\" id=\"email\" placeholder=\"Your email\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>How did you find us?</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<select name=\"find-us\" id=\"find-us\">\n\t\t\t\t\t\t\t\t<option value=\"friends\" selected>Friends</option>\n\t\t\t\t\t\t\t\t<option value=\"search\">Search engine</option>\n\t\t\t\t\t\t\t\t<option value=\"ad\">Advertisement</option>\n\t\t\t\t\t\t\t\t<option value=\"other\">Other</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>Drop us a line</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<textarea name=\"message\" placeholder=\"Your message\"></textarea>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>&nbsp;</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"submit\" value=\"Send it!\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/login.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\t\t<header>\n\t\t\t<div class=\"col span-1-of-3 cutout\">\n\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t</div>\n\t\t\t<div class=\"col span-2-of-3 sign-up-box\">\n\t\t\t\t\t\t<section>\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Sign in to Innovate</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<form method=\"post\" action=\"endpoints/login\" class=\"sign-up-form\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"email\">Email Address</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"email\" name=\"email\" id=\"email\" placeholder=\"Your email\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"password\">Password</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"password\" name=\"password\" id=\"password\" placeholder=\"Your password\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\n\t\t\t\t\t\t<div class=\"col span-3-of-3\">\n\t\t\t\t\t\t\t<input type=\"submit\" value=\"Log In\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row center\">\n\t\t\t\t\t\t<div class=\"col span-3-of-3\">\n\t\t\t\t\t\t\t<a href=\"#\">Forgot your password?</a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</section>\n\t\t\t</div>\n\t\t</header>\n\n\t\t<div id=\"unauthorized\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYour username & password are incorrect. Try again, or contact support to recover lost login details.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-ios-close icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\t\t<!-- <script src=\"res/js/login.js\"></script> -->\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/overview.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\n\t\t<header class=\"bar\">\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"overview.html\">Spending</a></li>\n\t\t\t\t\t\t<li><a href=\"bills.html\">Bills</a></li>\n\t\t\t\t\t\t<li><a href=\"accounts.html\">Accounts</a></li>\n\t\t\t\t\t\t<li><a href=\"chat.html\">Support</a></li>\n\t\t\t\t\t\t<li><a href=\"/endpoints/logout\">Logout</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t</header>\n\n\t\t<section class=\"section-spending\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Spending</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<h3><span class=\"small\">AED</span><span id='js-total'></span></h3>\n\t\t\t\t<p>Spent this month</p>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<section class=\"section-category-list\">\n\t\t\t<a id=\"groceries_link\" href=\"/transactions.html#groceries\">\n\t\t\t<div id=\"groceries_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-ios-cart icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Groceries</h3>\n\t\t\t\t\t<p id=\"groceries_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"groceries_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"eating_out_link\" href=\"/transactions.html#eating_out\">\n\t\t\t<div id=\"eating_out_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-android-restaurant icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Eating Out</h3>\n\t\t\t\t\t<p id=\"eating_out_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"eating_out_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"transport_link\" href=\"/transactions.html#transport\">\n\t\t\t<div id=\"transport_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-model-s icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Transport</h3>\n\t\t\t\t\t<p id=\"transport_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"transport_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"bills_link\" href=\"/transactions.html#bills\">\n\t\t\t<div id=\"bills_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-lightbulb icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Bills</h3>\n\t\t\t\t\t<p id=\"bills_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"bills_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"expenses_link\" href=\"/transactions.html#expenses\">\n\t\t\t<div id=\"expenses_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-ios-nutrition icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Expenses</h3>\n\t\t\t\t\t<p id=\"expenses_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"expenses_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"cash_link\" href=\"/transactions.html#cash\">\n\t\t\t<div id=\"cash_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-cash icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Cash</h3>\n\t\t\t\t\t<p id=\"cash_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"cash_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t<a id=\"holidays_link\" href=\"/transactions.html#holidays\">\n\t\t\t<div id=\"holidays_row\" class=\"row category\">\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<i class=\"ion-plane icon-big\"></i>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-3-of-5\">\n\t\t\t\t\t<h3>Holidays</h3>\n\t\t\t\t\t<p id=\"holidays_transaction_count\"></p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-5\">\n\t\t\t\t\t<h3 id=\"holidays_transaction_total\"></h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</a>\n\t\t</section>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"res/js/spending.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/res/css/chat.css",
    "content": "\n/* ----------------------------------------------------- */\n/* CHAT */\n/* ----------------------------------------------------- */\n\n#contentParent {\n  height: 80%;\n\tmargin-bottom: 20px;\n}\n\n.responsive-columns-wrapper {\n  display: -ms-flexbox;\n  display: -webkit-flex;\n  display: flex;\n  flex-direction: row;\n  -ms-display: flex;\n  -ms-flex-direction: row;\n}\n\n.responsive-column {\n  -webkit-flex: 1;\n  -ms-flex: 1;\n  flex: 1;\n  overflow: auto;\n}\n\n#chat-column-holder {\n  text-align: center;\n}\n\n.chat-column {\n  height: 100%;\n  padding: 0.9375rem 0 0.625rem 0;\n  margin: auto;\n  text-align: left;\n  max-width: 50rem;\n  min-width: 9.375rem;\n}\n\n#scrollingChat {\n  margin: 0.75rem;\n  overflow-y: auto;\n  overflow-x: hidden;\n  height: calc(100% - 4rem);\n}\n\n\n.message-inner {\n  opacity: 0;\n  margin-top: 0.9375rem;\n  -webkit-transition-property: opacity, margin-top;\n  -webkit-transition-duration: 0.75s;\n  -webkit-transition-timing-function: ease-in;\n  -moz-transition-property: opacity, margin-top;\n  -moz-transition-duration: 0.75s;\n  -moz-transition-timing-function: ease-in;\n  -o-transition-property: opacity, margin-top;\n  -o-transition-duration: 0.75s;\n  -o-transition-timing-function: ease-in;\n  -ms-transition-property: opacity, margin-top;\n  -ms-transition-duration: 0.75s;\n  -ms-transition-timing-function: ease-in;\n  transition-property: opacity, margin-top;\n  transition-duration: 0.75s;\n  transition-timing-function: ease-in;\n}\n\n.load .message-inner {\n  opacity: 1;\n  margin-top: 0.3125rem;\n}\n\n.from-user {\n  text-align: right;\n}\n\n.from-user .message-inner {\n  position: relative;\n  font-size: 1rem;\n  color: #fff;\n  letter-spacing: 0.015rem;\n  line-height: 1.3125rem;\n  background: #00B4A0;\n  border-radius: 1.25rem;\n  border-bottom-right-radius: 0;\n  text-align: left;\n  display: inline-block;\n  margin-left: 2.5rem;\n  min-width: 2.5rem;\n}\n\n.from-user .message-inner p {\n  margin: 0.3125rem;\n  padding: 0 0.9375rem;\n}\n\n.from-user .message-inner:before, .from-user .message-inner:after {\n  content: \"\";\n  position: absolute;\n}\n\n.from-user .message-inner:before {\n  z-index: -2;\n  bottom: -0.375rem;\n  right: 0;\n  height: 0.375rem;\n  width: 0.5rem;\n  background: #1cb3a0;\n}\n\n.from-user .message-inner:after {\n  z-index: -1;\n  bottom: -0.5rem;\n  right: 0;\n  height: 0.5rem;\n  width: 0.5rem;\n  background: #fff;\n  border-top-right-radius: 1.25rem;\n}\n\n.from-watson .message-inner {\n  position: relative;\n  border-radius: 1.5625rem;\n  font-size: 1rem;\n  color: #B5B5B5;\n  letter-spacing: 0.015rem;\n  line-height: 1.3125rem;\n}\n\n.from-watson.latest .message-inner {\n  color: #323232;\n}\n\n.from-watson p {\n  margin: 0.3125rem;\n  padding: 0 1.25rem;\n}\n\n.from-watson.latest.top p:before {\n  content: \".\";\n  color: #d24142;\n  background-image: url(\"images/marker.png\");\n  background-size: 0.3125rem 1.3125rem;\n  position: absolute;\n  z-index: 2;\n  left: 0.4375rem;\n  width: 0.3125rem;\n  height: 1.3125rem;\n  line-height: 1.3125rem;\n}\n\n\n#textInput {\n  border: none;\n  outline: none;\n  background: transparent;\n  font-size: 1rem;\n  color: #323232;\n  letter-spacing: 0.015rem;\n  line-height: 1.3125rem;\n  height: 2.5rem;\n  max-width: 100%;\n  padding-left: 0.125rem;\n  margin-bottom: -0.125rem;\n  font-family: Helvetica Neue for IBM, Helvetica Neue, Helvetica, Arial, sans-serif;\n\n}\n\n\n#textInput.underline {\n  border-bottom: 2px solid #00B4A0;\n}\n\n::-webkit-input-placeholder {\n  color: #B5B5B5;\n}\n\n::-moz-placeholder {\n  color: #B5B5B5;\n  opacity:  1;\n}\n\ninput:-moz-placeholder {\n  color: #B5B5B5;\n  opacity:  1;\n}\n\n:-ms-input-placeholder {\n  color: #B5B5B5;\n}\n\n::-ms-clear {\n  display: none;\n}\n\n.inputOutline {\n  display: block;\n  border-bottom: 0.0625rem solid #aeaeae;\n  margin-left: 0.5rem;\n  margin-right: 0.5rem;\n}\n\n#textInputDummy {\n  position:absolute;\n  white-space:pre;\n  top: 0;\n  left: -1000%;\n  opacity: 0;\n}\n\n#payload-column {\n\tdisplay: none;\n  font-family: Monaco, monospace;\n  font-size: 0.75rem;\n  letter-spacing: 0;\n  line-height: 1.125rem;\n  background-color: #23292A;\n  color: #fff;\n  overflow-x: auto;\n\n  width: 45%;\n  max-width: 32.0625rem;\n  min-width: 29.6875rem;\n}\n\n#payload-column.full {\n  width: 100%;\n  max-width: none;\n  min-width: initial;\n}\n\n#payload-column .header-text, #payload-column #payload-initial-message {\n  font-family: Helvetica Neue for IBM, Helvetica Neue, Helvetica, Arial, sans-serif;\n  font-size: 1.125rem;\n  color: #9E9E9E;\n  letter-spacing: 0.01875rem;\n  padding: 0.5rem;\n  padding-left: 2.5rem;\n  background: #383D3E;\n}\n.payload .line-numbers, .payload .payload-text {\n  padding: 0.5rem;\n}\n\n.line-numbers {\n  width: 2rem;\n  color: #898989;\n  text-align: right;\n}\n\npre {\n  margin: 0;\n  word-wrap: normal;\n}\n\n.string {\n  color: #54EED0;\n}\n\n.boolean, .null, .number {\n  color: #CE8EFF;\n}\n\n.key {\n  color: #66B7FF;\n}"
  },
  {
    "path": "portal/public/res/css/queries.css",
    "content": "/* LARGE TABLETS TO DESKTOP BROWSERS */\n\n@media only screen and (max-width: 1200px) {\n\t.hero-text-box { width: 100%; padding: 0 3%; }\n\t.row { padding: 0 3%; }\n}\n\n/* TABLETS & PORTRAIT MODE */\n\n@media only screen and (max-width: 1023px) {\n\tbody { font-size: 80%; }\n\tsection { padding 60px 0; }\n\t.long-copy { width: 80%; margin-left: 10% }\n}\n\n/* LARGE PHONES TO SMALL TABLETS */\n\n@media only screen and (max-width: 767px) {\n\t.steps-box { margin-top: 10px; }\n\t.steps-box:first-child { margin-top: 10px; margin-left: -60px; }\n\t.steps-box:last-child { margin-top: 10px; }\n\t.steps-box { margin-top: 10px; }\n\t.works-step { margin-bottom: 20px; }\n\t.works-step:last-of-type { margin-bottom: 30px; }\n\t.app-screen { width: 40%; }\n\t.works-step div { height: 35px; width: 35px; font-size: 135%; margin-right: 15px;}\n\t.btn-app img { height: 30px; }\n\t.plan-box ul li .icon-small { width: 2%}\n\t.plan-price { font-size: 200%}\n\t.plan-box .btn { padding: 10%;}\n\t.section-cities .icon-small { width: 2%}\n\t.contact-form { width: 90%; }\n\t.mobile-nav-icon { display: inline-block; }\n\t.main-nav { float: left; margin-top: 2px; display: none; }\n\t.main-nav li { display: block; }\n\t.main-nav li a:link, .main-nav li a:visited { display: block; border: 0; }\n\t.sticky-nav .main-nav { margin-top: 0px; }\n\t.sticky-nav .mobile-nav-icon i { color: #555; }\n}\n\n/* SMALL PHONES */\n\n@media only screen and (max-width: 480px) {\n\t.logo { height: 80px; }\n\t.hero-text-box .btn { margin-bottom: 10px; }\n\t.section-features h3, .section-features p { text-align: center; }\n\t.app-screen { width: 30%; float: left; margin: 0 0 20px 50%; }\n\t.works-step div { height: 20px; width: 20px; font-size: 80%; padding: 0.5%; font-weight: 500;}\n\t.btn-app img { height: 35px; padding-left: 3%}\n\t.plan-box { font-size: 120% }\n\t.plan-box ul li .icon-small { width: 5%}\n\t.plan-price { font-size: 300%}\n\t.plan-box .btn { padding: 5%;}\n\t.contact-form .row { padding: 5px; }\n\tfooter { padding-left: 15px; }\n\t.footer-nav { float: none; padding-bottom: 10px; width: 120%; }\n\t.social-links { padding-bottom: 10px; float: none; }\n\t.section-spending { padding: 12px; }\n\t.section-spending h2 { margin-bottom: 15px }\n\t.section-spending h3 { font-size: 200%; }\n\t.section-spending .small { font-size: 50%; }\n\t.section-spending p { font-weight: 200; }\n\t.section-category-list { padding-top: 0px; }\n\t.section-category-list .row { margin-bottom: 5px; }\n\t.section-category-list .icon-big { padding: 0px; margin: 0px; }\n\t.section-category-list h3 { text-align: center; font-size: 120%; padding-bottom: 10px;}\n\t.section-category-list p { text-align: center; font-size: 90%; padding-bottom: 5px; }\n\t.section-bill-list { padding-top: 0px; }\n\t.section-bill-list h3 { font-size: 120%; text-align: center; }\n\t.section-bill-list p { font-size: 80%; text-align: center; padding-bottom: 5px;}\n\t.service-provider-logo { width: 40px; height: auto; margin-left: 45%; }\n\t.section-bill-list .btn {margin-left: calc(47.5% - 20px); padding: 3px 20px; margin-bottom: 10px; margin-top: 5px;}\n\t.section-transaction-list .category { margin-bottom: 10px; margin-top: 10px; }\n\t.section-transaction-list .row { border-bottom: 0.2px solid #ccc;}\n\t.section-transaction-list .transaction {display: inline-flex; width: 100%; padding-bottom: 10px;}\n}\n"
  },
  {
    "path": "portal/public/res/css/styles.css",
    "content": "/* ----------------------------------------------------- */\n/* BASIC SETUP */\n/* ----------------------------------------------------- */\n\n* {\n\tmargin: 0;\n\tpadding: 0;\n\t-webkit-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n\nhtml {\n\theight: 100%;\n\tbackground-color: #fff;\n\tcolor: #555;\n\tfont-family: 'Lato', 'Arial', 'sans-serif';\n\tfont-size: 2opx;\n\tfont-weight: 300;\n\ttext-rendering: optimizeLegibility;\n}\n\nbody {\n\theight: 100%;\n}\n\n.clearfix {zoom: 1}\n.clearfix:after {\n\tcontent: '.';\n\tclear: both;\n\tdisplay: block;\n\theight: 0;\n\tvisibility: hidden;\n}\n\n/* ----------------------------------------------------- */\n/* HEADER */\n/* ----------------------------------------------------- */\n\nheader {\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.7)), to(rgba(0, 0, 0, 0.7))),url(images/hero.jpg);\n\tbackground-image: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),url(images/hero.jpg);\n\tbackground-size: cover;\n\tbackground-position: center;\n\theight: 100vh;\n\tbackground-attachment: fixed;\n}\n\n.bar {\n\theight: 20%;\n}\n\n.hero-text-box {\n\tposition: absolute;\n\twidth: 1140px;\n\ttop: 50%;\n\tleft: 50%;\n\t-webkit-transform: translate(-50%, -50%);\n\ttransform: translate(-50%, -50%);\n}\n\n.logo {\n\theight: 100px;\n\twidth: auto;\n\tfloat: left;\n\tmargin-top: 20px;\n}\n\n.logo-black {\n\tdisplay: none;\n\theight: 50px;\n\twidth: auto;\n\tfloat: left;\n\tmargin: 5px 0;\n}\n\n/* MAIN NAV */\n\n.main-nav {\n\tfloat: right;\n\tlist-style: none;\n\tmargin-top: 50px;\n}\n\n.main-nav li {\n\tdisplay: inline-block;\n\tmargin-left: 20px;\n}\n\n.main-nav li a:link,\n.main-nav li a:visited {\n\tpadding: 8px 0;\n\tcolor: #fff;\n\ttext-decoration: none;\n\ttext-transform: uppercase;\n\tfont-size: 90%;\n\tborder-bottom: 2px solid transparent;\n\t-webkit-transition: border-bottom 0.2s;\n\ttransition: border-bottom 0.2s;\n}\n\n.main-nav li a:hover,\n.main-nav li a:active {\n\tborder-bottom: 2px solid #d24142;\n}\n\n/* MOBILE NAV */\n\n.mobile-nav-icon {\n\tfloat: right;\n\tmargin-top: 20px;\n\tcursor: pointer;\n\tdisplay: none;\n}\n\n.mobile-nav-icon i {\n\tfont-size: 200%;\n\tcolor: #fff;\n}\n\n\n/* STICKY NAV */\n\n.sticky-nav {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tbackground-color: rgba(255, 255, 255, 0.98);\n\tbox-shadow: 0 2px 2px #efefef;\n\tz-index: 9999;\n}\n\n.sticky-nav .main-nav {\n\tmargin-top: 18px;\n}\n\n.sticky-nav .main-nav li a:link,\n.sticky-nav .main-nav li a:visited {\n\tpadding: 16px 0;\n\tcolor: #555;\n}\n\n.sticky-nav .logo-black {\n\tdisplay: block;\n}\n.sticky-nav .logo { display: none; }\n\n/* ----------------------------------------------------- */\n/* REUSABLE COMPONENTS */\n/* ----------------------------------------------------- */\n\n.row {\n\tmax-width: 1140px;\n\tmargin: 0 auto;\n}\n\n.left-align {\n\ttext-align: left;\n}\n\n.center {\n\tmargin: auto;\n}\n\nsection {\n\tpadding: 80px 0;\n}\n\n.box {\n\tpadding: 1%;\n}\n\n\n/* ------- HEADINGS ------- */\n\nh1,\nh2,\nh3 {\n\tfont-weight: 300;\n\ttext-transform: uppercase;\n}\n\nh1 {\n\tmargin-top: 0;\n\tmargin-bottom: 20px;\n\tcolor: #fff;\n\tfont-size: 240%;\n\tword-spacing: 4px;\n\tletter-spacing: 1px;\n}\n\nh2 {\n\tfont-size: 180%;\n\tword-spacing: 2px;\n\ttext-align: center;\n\tmargin-bottom: 30px;\n\tletter-spacing: 1px;\n}\n\nh2:after {\n\tdisplay: block;\n\theight: 2px;\n\tbackground-color: #d24142;\n\tcontent: \" \";\n\twidth: 100px;\n\tmargin: 0 auto;\n\tmargin-top: 30px;\n}\n\nh3 {\n\tfont-size: 110%;\n\tmargin-bottom: 15px;\n}\n\n/* ------- PARAGRAPHS ------- */\n\n.long-copy {\n\tline-height: 145%;\n\twidth: 80%;\n\tmargin-left: 10%;\n\tfont-size: 130%;\n}\n\n.box p {\n\tfont-size: 90%;\n\tline-height: 145%;\n}\n\n/* ------- ICONS ------- */\n\n.icon-big {\n\tfont-size: 350%;\n\tdisplay: block;\n\tcolor: #d24142;\n\tmargin-bottom: 10px;\n\tmargin-left: -25px;\n\ttext-align: center;\n}\n\n.icon-small {\n\tdisplay: inline-block;\n\twidth: 30px;\n\ttext-align: center;\n\tcolor: #d24142;\n\tfont-size: 120%;\n\tline-height: 120%;\n\tvertical-align: middle;\n\tmargin-top: -5px;\n\tmargin-right: 10px;\n}\n\n/* ------- ICONS ------- */\n\na:link,\na:visited {\n\tcolor: #d24142;\n\ttext-decoration: none;\n\tpadding-bottom: 1px;\n\tborder-bottom: 1px solid #d24142;\n\t-webkit-transition: border-botton 0.2s, color 0.2s;\n\ttransition: border-botton 0.2s, color 0.2s;\n}\n\na:hover,\na:active {\n\tcolor: #555;\n\tborder-bottom: 1px solid transparent;\n}\n\n/* ------- BUTTONS ------- */\n\n.btn:link,\n.btn:visited,\ninput[type=submit] {\n\tdisplay: inline-block;\n\tpadding: 10px 30px;\n\tfont-weight: 300;\n\ttext-decoration: none;\n\tborder-radius: 200px;\n\t-webkit-transition: background-color 0.2s, border 0.2s, color 0.2s;\n\ttransition: background-color 0.2s, border 0.2s, color 0.2s;\n}\n\n.btn:hover,\n.btn:active,\ninput[type=submit] {\n\tbackground-color: #d24142;\n}\n\n.btn-full:link,\n.btn-full:visited,\ninput[type=submit] {\n\tbackground-color: #d24142;\n\tborder: 1px solid #d24142;\n\tcolor: #fff;\n\tmargin-right: 15px;\n}\n\n.btn-full:hover,\n.btn-full:active,\ninput[type=submit] {\n\tbackground-color: #d24142;\n\tborder: 1px solid #d24142;\n}\n\n.btn-ghost:link,\n.btn-ghost:visited {\n\tborder: 1px solid #d24142;\n\tcolor: #d24142;\n}\n\n.btn-ghost:hover,\n.btn-ghost:active {\n\tborder: 1px solid #d24142;\n\tcolor: #fff;\n}\n\n.btn-disabled:link,\n.btn-disabled:visited {\n\tbackground-color: #ccc;\n\tborder: 1px solid #ccc;\n\tcolor: #fff;\n\tmargin-right: 15px;\n\tcursor: not-allowed;\n}\n\n.btn-disabled:hover,\n.btn-disabled:active {\n\tbackground-color: #ccc;\n\tborder: 1px solid #ccc;\n\tcursor: not-allowed;\n}\n\n/* ------- POPUPS ------- */\n\n.overlay {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  background: rgba(0, 0, 0, 0.6);\n  transition: opacity 0.5s;\n  visibility: hidden;\n  opacity: 0;\n}\n\n.overlay:target {\n  visibility: visible;\n  opacity: 1;\n}\n\n.popup {\n  margin: calc(20% + 20px) auto;\n\tpadding: 30px 15px;;\n  background: #fff;\n  border-radius: 5px;\n\tmax-width: 600px;\n  width: 60%;\n\tmin-height: 30%;\n\theight: auto;\n  position: relative;\n}\n\n.popup h2 {\n  margin-top: 0;\n  color: #000;\n}\n\n.popup .close {\n  position: absolute;\n  top: 20px;\n  right: 20px;\n  font-size: 180%;\n  font-weight: 200;\n  text-decoration: none;\n  color: #000;\n\tborder-bottom: none;\n}\n\n.popup .close:hover {\n  color: #d24142;\n\tfont-weight: 300;\n}\n\n.popup .content {\n  overflow: auto;\n\ttext-align: center;\n\tmax-height: 50%;\n\tmargin-bottom: 5px;\n}\n\n.popup .btn {\n\tmargin-top: 15px;\n\tmargin-bottom: 10px;\n\tmargin-left: calc(43% - 20px);\n\tpadding: 10px 20px;\n}\n\n.popup .icon-big {\n\tmargin: auto;\n}\n\n\n/* ----------------------------------------------------- */\n/* FEATURES */\n/* ----------------------------------------------------- */\n\n.section-features .long-copy {\n\tmargin-bottom: 30px;\n}\n\n/* ----------------------------------------------------- */\n/* CONTACT FORM */\n/* ----------------------------------------------------- */\n\n.section-form {\n\tbackground-color: #f4f4f4;\n}\n.contact-form {\n\twidth: 60%;\n\tmargin: 0 auto;\n}\n\n.contact-form input[type=text],\n.contact-form input[type=email],\n.contact-form select,\n.contact-form textarea {\n\twidth: 100%;\n\tpadding: 7px;\n\tborder-radius: 3px;\n\tborder: 1px solid #ccc;\n}\n\n.contact-form textarea {\n\theight: 100px;\n}\n\n.contact-form input[type=checkbox] {\n\tmargin: 10px 5px 10px 0;\n}\n\n*:focus {\n\toutline: none;\n}\n\n/* ----------------------------------------------------- */\n/* FOOTER */\n/* ----------------------------------------------------- */\n\nfooter {\n\tbackground-color: #333;\n\tpadding: 40px;\n}\n\nfooter p:last-child{\n\tpadding-top: 10px;\n\tcolor: #d24142;\n}\n\n.footer-nav {\n\tlist-style: none;\n\tfloat: left;\n}\n\n.social-links {\n\tlist-style: none;\n\tfloat: right;\n}\n\n.footer-nav li,\n.social-links li {\n\tdisplay: inline-block;\n\tmargin-right: 20px;\n}\n\n.footer-nav li:last-child,\n.social-links li:last-child {\n\tmargin-right: 0;\n}\n\n.footer-nav li a:link,\n.footer-nav li a:visited,\n.social-links li a:link,\n.social-links li a:visited {\n\ttext-decoration: none;\n\tborder: 0;\n\tcolor: #888;\n}\n\n.footer-nav li a:hover,\n.footer-nav li a:active {\n\tcolor: #ddd;\n\tcursor: pointer;\n}\n\n.social-links li a:link,\n.social-links li a:visited {\n\tfont-size: 150%;\n}\n\n.ion-social-facebook,\n.ion-social-twitter,\n.ion-social-googleplus,\n.ion-social-instagram {\n\t-webkit-transition: color 0.2s;\n\ttransition: color 0.2s;\n}\n\n.ion-social-facebook:hover {\n\tcolor: #3b5998;\n}\n\n.ion-social-twitter:hover {\n\tcolor: #00aced;\n}\n\n.ion-social-googleplus:hover {\n\tcolor: #dd4b39;\n}\n\n.ion-social-instagram:hover {\n\tcolor: #8a3ab9;\n}\n\n.footer p {\n\tcolor: #888;\n\ttext-align: center;\n\tfont-size: 90%;\n\tmargin-top: 20px;\n}\n\n/* ----------------------------------------------------- */\n/* SIGN UP & LOGIN FORMS */\n/* ----------------------------------------------------- */\n\n.cutout {\n\tpadding: 0px 30px 30px 30px;\n}\n.sign-up-box {\n\tmargin: 0;\n\tpadding: 0;\n\theight: 100vh;\n\tbackground-color: #f4f4f4;\n}\n\n.sign-up-form {\n\twidth: 85%;\n\tmargin: 0 auto;\n}\n\n.sign-up-form input,\n.sign-up-form select {\n\twidth: 100%;\n\tpadding: 5px;\n\tmargin-bottom: 15px;\n\tborder-radius: 3px;\n\tborder: 1px solid #ccc;\n}\n\n.sign-up-form input[type=submit] {\n\tborder-radius: 50px;\n\tmargin-bottom: 5px;\n}\n\n.sign-up-form input[type=checkbox] {\n\twidth: 15px;\n}\n\n.sign-up-form .center {\n\ttext-align: center;\n}\n\n/* ----------------------------------------------------- */\n/* SPENDING */\n/* ----------------------------------------------------- */\n\n\n/* ------- OVERVIEW ------- */\n\n.section-spending {\n\tbackground-color: #f4f4f4;\n\ttext-align: center;\n\tpadding: 30px;\n\tborder-bottom: 0.2px solid #ccc;\n\tbox-shadow: 0 2px 2px #efefef;\n}\n\n.section-spending h3 {\n\tfont-size: 250%;\n\tfont-weight: 300;\n\tmargin-bottom: 0;\n}\n\n.section-spending .small {\n\tfont-size: 65%;\n}\n\n.section-spending p {\n\tfont-weight: 200;\n}\n\n/* ------- CATEGORY LIST ------- */\n\n.section-category-list {\n\tpadding-top: 15px;\n}\n\n.section-category-list .row {\n\tpadding-top: 10px;\n\tborder-bottom: 0.2px solid #ccc;\n}\n\n.section-category-list .row:hover,\n.section-category-list .row:active {\n\tcolor: #d24142;\n\tcursor: pointer;\n\tfont-size: 102%;\n\tbox-shadow: 0px 3.5px 3.5px #efefef;\n}\n\n.section-category-list .icon-big {\n\ttext-align: center;\n\tpadding-left: 70%;\n\tcursor: pointer;\n}\n\n.section-category-list h3 {\n\ttext-align: left;\n\tfont-size: 140%;\n\tpadding-left: 20;\n\tmargin-bottom: 3px;\n}\n\n.section-category-list p {\n\ttext-align: left;\n\tfont-size: 110%;\n\tcolor: #888;\n}\n\n.greyed-out {\n\tfont-weight: 100;\n\tcolor: #bfbfbf;\n}\n\n.greyed-out .icon-big {\n\tcolor: #e0e5e8;\n}\n\n.section-category-list .row.greyed-out:hover,\n.section-category-list .row.greyed-out:active {\n\tcolor: #bfbfbf;\n\tcursor: default;\n\tfont-size: 100%;\n\tbox-shadow: 0 0px 0px;\n}\n\n/* ----------------------------------------------------- */\n/* BILLS */\n/* ----------------------------------------------------- */\n\n.section-bill-list {\n\tpadding-top: 15px;\n}\n\n.section-bill-list .row {\n\tpadding-top: 10px;\n\tborder-bottom: 0.2px solid #ccc;\n}\n\n.section-bill-list h3 {\n\tfont-size: 130%;\n\tmargin-bottom: 5px;\n}\n\n.section-bill-list p {\n\tfont-size: 90%;\n}\n\n.service-provider-logo {\n\twidth: 50px;\n\theight: auto;\n\tmargin-left: 50%;\n\tmargin-bottom: 10px;\n}\n\n/* ----------------------------------------------------- */\n/* TRANSACTIONS */\n/* ----------------------------------------------------- */\n\n.section-transaction-list {\n\tpadding-top: 0px;\n}\n\n.section-transaction-list .category {\n\tfont-size: 130%;\n\tmargin-bottom: 0px;\n\tcolor: #888888;\n\tmargin-top: 15px;\n}\n\n.section-transaction-list h2 {\n\tfont-size: 120%;\n\tmargin-bottom: 0px;\n\ttext-align: left;\n}\n\n.section-transaction-list h2:after {\n\tbackground-color: #d24142;\n\tcontent: \" \";\n\twidth: 100%;\n\tmargin-top: 15px;\n}\n\n.section-transaction-list .row {\n\tborder-bottom: 0.2px solid #ccc;\n}\n\n.section-transaction-list h3 {\n\tfont-size: 130%;\n\tmargin-bottom: 5px;\n\tmargin-left: 20px;\n}\n\n.section-transaction-list h3:last-child {\n\tmargin-top: 3%;\n}\n\n.section-transaction-list p {\n\tfont-size: 80%;\n\tmargin-left: 20px;\n}\n"
  },
  {
    "path": "portal/public/res/js/accounts.js",
    "content": "$(document).ready(function() {\n  var http = new XMLHttpRequest();\n  var getUrl = window.location;\n  var baseUrl = getUrl.protocol + \"//\" + getUrl.host;\n  var AccountsEndpoint = baseUrl + '/endpoints/accounts/get';\n  console.log('Accounts >>>> ', AccountsEndpoint)\n  var uuid = 0;\n  var selectors = {\n    current: {\n        label: '#current_label',\n        number: '#current_number',\n        balance: '#current_balance',\n        button: '#current_button'\n    },\n    savings: {\n        label: '#savings_label',\n        number: '#savings_number',\n        balance: '#savings_balance',\n        button: '#savings_button'\n    },\n    credit: {\n        label: '#credit_label',\n        number: '#credit_number',\n        balance: '#credit_balance',\n        button: '#credit_button'\n    },\n    prepaid: {\n        label: '#prepaid_label',\n        number: '#prepaid_number',\n        balance: '#prepaid_balance',\n        button: '#prepaid_button'\n    }\n  }\n\n  //Ensure authenticated and get uuid\n  http.open('GET', '/endpoints/auth', true);\n  http.setRequestHeader('Content-type', 'application/json');\n  http.onreadystatechange = function() {\n    if (http.readyState === 4 && http.status === 500) {\n      window.location.replace('/index.html')\n    }\n    else if (http.readyState === 4 && http.status === 200 && http.responseText) {\n      var response = JSON.parse(http.responseText)\n      uuid = response.uuid\n      http.open('POST', AccountsEndpoint, true);\n      http.setRequestHeader('Content-type', 'application/json');\n      http.onreadystatechange = function() {\n        if (http.readyState === 4 && http.status === 200 && http.responseText) {\n          var accounts = JSON.parse(http.responseText);\n          var total = 0;\n          var innerHTML = ''\n          for (var type in selectors) {\n            var account = accounts.find(item => item.type==type)\n            if (account) {\n              $(selectors[type].label).html('Account No. ');\n              $(selectors[type].number).html(account.number);\n              $(selectors[type].balance).html('AED ' + account.balance);\n              $(selectors[type].button).html('Transfer');\n              if (account.balance <= 0) $(selectors[type].button).removeClass('btn-ghost').addClass('btn-disabled')\n              $(selectors[type].button).attr(\"href\", \"#confirm-popup-transfer\");\n              total += account.balance\n              innerHTML +=\n              `<option value=\"` + account.number + `\">` + account.number + ` (` + type + `)` + `</option>`\n            }\n            else {\n              $(selectors[type].button).html('Activate');\n              $(selectors[type].button).attr(\"href\", \"#confirm-popup-\" + type);\n              $(selectors[type].button).removeClass('btn-disabled').addClass('btn-ghost')\n            }\n          }\n          $('#from').html(innerHTML)\n          $('#to').html(innerHTML)\n          $('#js-balance').html(total)\n        }\n      };\n      http.send(JSON.stringify({'uuid': uuid}));\n    }\n  };\n  http.send();\n})\n"
  },
  {
    "path": "portal/public/res/js/api.js",
    "content": "// The Api module is designed to handle all interactions with the server\n\nvar Api = (function() {\n  var requestPayload;\n  var responsePayload;\n  var getUrl = window.location;\n  var baseUrl = getUrl.protocol + \"//\" + getUrl.host;\n  var messageEndpoint = baseUrl + '/endpoints/support/chat';\n  console.log('Support >>>> ', messageEndpoint)\n\n  // Publicly accessible methods defined\n  return {\n    sendRequest: sendRequest,\n\n    // The request/response getters/setters are defined here to prevent internal methods\n    // from calling the methods without any of the callbacks that are added elsewhere.\n    getRequestPayload: function() {\n      return requestPayload;\n    },\n    setRequestPayload: function(newPayloadStr) {\n      requestPayload = JSON.parse(newPayloadStr);\n    },\n    getResponsePayload: function() {\n      return responsePayload;\n    },\n    setResponsePayload: function(newPayloadStr) {\n      responsePayload = JSON.parse(newPayloadStr);\n    }\n  };\n\n  // Send a message request to the server\n  function sendRequest(text, context) {\n    // Build request payload\n    var payloadToWatson = {};\n    if (text) {\n      payloadToWatson.input = {\n        text: text\n      };\n    }\n    if (context) {\n      payloadToWatson.context = context;\n    }\n\n    // Built http request\n    var http = new XMLHttpRequest();\n    http.open('POST', messageEndpoint, true);\n    http.setRequestHeader('Content-type', 'application/json');\n    http.onreadystatechange = function() {\n      if (http.readyState === 4 && http.status === 200 && http.responseText) {\n        Api.setResponsePayload(http.responseText);\n      }\n    };\n\n    var params = JSON.stringify(payloadToWatson);\n    // Stored in variable (publicly visible through Api.getRequestPayload)\n    // to be used throughout the application\n    if (Object.getOwnPropertyNames(payloadToWatson).length !== 0) {\n      Api.setRequestPayload(params);\n    }\n\n    // Send request\n    http.send(params);\n  }\n}());\n"
  },
  {
    "path": "portal/public/res/js/bills.js",
    "content": "$(document).ready(function() {\n\n  var http = new XMLHttpRequest();\n  var getUrl = window.location;\n  var baseUrl = getUrl.protocol + \"//\" + getUrl.host;\n  var billsEndpoint = baseUrl + '/endpoints/bills/get';\n  console.log('Bills >>>> ', billsEndpoint)\n  var uuid = 0;\n  var selectors = {\n    utilities: {\n        entity: '#utilities_entity',\n        account: '#utilities_account',\n        amount: '#utilities_amount',\n        popup_entity: '#utilities_bill_entity',\n        popup_account: '#utilities_bill_account',\n        popup_amount: '#utilities_bill_amount',\n        button: '#utilities_pay_button',\n        confirm_button: '#utilities_confirm_button'\n    },\n    home_entertainment: {\n        entity: '#home_entertainment_entity',\n        account: '#home_entertainment_account',\n        amount: '#home_entertainment_amount',\n        popup_entity: '#home_entertainment_bill_entity',\n        popup_account: '#home_entertainment_bill_account',\n        popup_amount: '#home_entertainment_bill_amount',\n        button: '#home_entertainment_pay_button',\n        confirm_button: '#home_entertainment_confirm_button'\n    },\n    mobile_phone: {\n        entity: '#mobile_phone_entity',\n        account: '#mobile_phone_account',\n        amount: '#mobile_phone_amount',\n        popup_entity: '#mobile_phone_bill_entity',\n        popup_account: '#mobile_phone_bill_account',\n        popup_amount: '#mobile_phone_bill_amount',\n        button: '#mobile_phone_pay_button',\n        confirm_button: '#mobile_phone_confirm_button'\n    },\n    credit_card: {\n        entity: '#credit_card_entity',\n        account: '#credit_card_account',\n        amount: '#credit_card_amount',\n        popup_entity: '#credit_card_bill_entity',\n        popup_account: '#credit_card_bill_account',\n        popup_amount: '#credit_card_bill_amount',\n        button: '#credit_card_pay_button',\n        confirm_button: '#credit_card_confirm_button'\n    }\n  }\n\n  //Ensure authenticated and get uuid\n  http.open('GET', '/endpoints/auth', true);\n  http.setRequestHeader('Content-type', 'application/json');\n  http.onreadystatechange = function() {\n    if (http.readyState === 4 && http.status === 500) {\n      window.location.replace('/index.html')\n    }\n    else if (http.readyState === 4 && http.status === 200 && http.responseText) {\n      var response = JSON.parse(http.responseText)\n      console.log('response >>>> ', response)\n      uuid = response.uuid\n      http.open('POST', billsEndpoint, true);\n      http.setRequestHeader('Content-type', 'application/json');\n      http.onreadystatechange = function() {\n        if (http.readyState === 4 && http.status === 200 && http.responseText) {\n          var bills = JSON.parse(http.responseText);\n          var total = 0;\n          for (var category in selectors) {\n            var bill = bills.find(item => item.category==category)\n            if (bill) {\n              $(selectors[category].entity).html(bill.entity); $(selectors[category].popup_entity).html(bill.entity);\n              $(selectors[category].account).html(' Account No. ' + bill.account_no); $(selectors[category].popup_account).html(' Account No. ' + bill.account_no);\n              $(selectors[category].amount).html('AED ' + bill.amount); $(selectors[category].popup_amount).html('AED ' + bill.amount);\n              $(selectors[category].confirm_button).attr(\"href\", \"/endpoints/bills/pay?amount=\"+bill.amount+\"&entity=\"+bill.entity+\"&category=\"+category+\"&account=\"+bill.account_no);\n              if (bill.amount <= 0) $(selectors[category].button).removeClass('btn-ghost').addClass('btn-disabled')\n              total += bill.amount\n            }\n            else {\n              $(selectors[category].button).removeClass('btn-ghost').addClass('btn-disabled')\n            }\n          }\n          $('#js-total').html(`<span class=\"small\">AED </span>` + total)\n        }\n      };\n      http.send(JSON.stringify({'uuid': uuid}));\n    }\n  };\n  http.send();\n})\n"
  },
  {
    "path": "portal/public/res/js/common.js",
    "content": "// The Common module is designed as an auxiliary module\n// to hold functions that are used in multiple other modules\n/* eslint no-unused-vars: \"off\" */\n\nvar Common = (function() {\n  // Publicly accessible methods defined\n  return {\n    buildDomElement: buildDomElementFromJson,\n    fireEvent: fireEvent,\n    listForEach: listForEach\n  };\n\n  // Take in JSON object and build a DOM element out of it\n  // (Limited in scope, cannot necessarily create arbitrary DOM elements)\n  // JSON Example:\n  //  {\n  //    \"tagName\": \"div\",\n  //    \"text\": \"Hello World!\",\n  //    \"className\": [\"aClass\", \"bClass\"],\n  //    \"attributes\": [{\n  //      \"name\": \"onclick\",\n  //      \"value\": \"alert(\"Hi there!\")\"\n  //    }],\n  //    \"children: [{other similarly structured JSON objects...}, {...}]\n  //  }\n  function buildDomElementFromJson(domJson) {\n    // Create a DOM element with the given tag name\n    var element = document.createElement(domJson.tagName);\n\n    // Fill the \"content\" of the element\n    if (domJson.text) {\n      element.innerHTML = domJson.text;\n    } else if (domJson.html) {\n      element.insertAdjacentHTML('beforeend', domJson.html);\n    }\n\n    // Add classes to the element\n    if (domJson.classNames) {\n      for (var i = 0; i < domJson.classNames.length; i++) {\n        element.classList.add(domJson.classNames[i]);\n      }\n    }\n    // Add attributes to the element\n    if (domJson.attributes) {\n      for (var j = 0; j < domJson.attributes.length; j++) {\n        var currentAttribute = domJson.attributes[j];\n        element.setAttribute(currentAttribute.name, currentAttribute.value);\n      }\n    }\n    // Add children elements to the element\n    if (domJson.children) {\n      for (var k = 0; k < domJson.children.length; k++) {\n        var currentChild = domJson.children[k];\n        element.appendChild(buildDomElementFromJson(currentChild));\n      }\n    }\n    return element;\n  }\n\n  // Trigger an event to fire\n  function fireEvent(element, event) {\n    var evt;\n    if (document.createEventObject) {\n      // dispatch for IE\n      evt = document.createEventObject();\n      return element.fireEvent('on' + event, evt);\n    }\n    // otherwise, dispatch for Firefox, Chrome + others\n    evt = document.createEvent('HTMLEvents');\n    evt.initEvent(event, true, true); // event type,bubbling,cancelable\n    return !element.dispatchEvent(evt);\n  }\n\n  // A function that runs a for each loop on a List, running the callback function for each one\n  function listForEach(list, callback) {\n    for (var i = 0; i < list.length; i++) {\n      callback.call(null, list[i]);\n    }\n  }\n}());\n"
  },
  {
    "path": "portal/public/res/js/conversation.js",
    "content": "// The ConversationPanel module is designed to handle\n// all display and behaviors of the conversation column of the app.\n/* eslint no-unused-vars: \"off\" */\n/* global Api: true, Common: true*/\n\nvar ConversationPanel = (function() {\n  var settings = {\n    selectors: {\n      chatBox: '#scrollingChat',\n      fromUser: '.from-user',\n      fromWatson: '.from-watson',\n      latest: '.latest'\n    },\n    authorTypes: {\n      user: 'user',\n      watson: 'watson'\n    }\n  };\n\n  // Publicly accessible methods defined\n  return {\n    init: init,\n    inputKeyDown: inputKeyDown\n  };\n\n  // Initialize the module\n  function init() {\n    chatUpdateSetup();\n    Api.sendRequest( '', null );\n    setupInputBox();\n  }\n  // Set up callbacks on payload setters in Api module\n  // This causes the displayMessage function to be called when messages are sent / received\n  function chatUpdateSetup() {\n    var currentRequestPayloadSetter = Api.setRequestPayload;\n    Api.setRequestPayload = function(newPayloadStr) {\n      currentRequestPayloadSetter.call(Api, newPayloadStr);\n      displayMessage(JSON.parse(newPayloadStr), settings.authorTypes.user);\n    };\n\n    var currentResponsePayloadSetter = Api.setResponsePayload;\n    Api.setResponsePayload = function(newPayloadStr) {\n      currentResponsePayloadSetter.call(Api, newPayloadStr);\n      displayMessage(JSON.parse(newPayloadStr), settings.authorTypes.watson);\n    };\n  }\n\n// Set up the input box to underline text as it is typed\n  // This is done by creating a hidden dummy version of the input box that\n  // is used to determine what the width of the input text should be.\n  // This value is then used to set the new width of the visible input box.\n  function setupInputBox() {\n    var input = document.getElementById('textInput');\n    var dummy = document.getElementById('textInputDummy');\n    var minFontSize = 14;\n    var maxFontSize = 16;\n    var minPadding = 4;\n    var maxPadding = 6;\n\n    // If no dummy input box exists, create one\n    if (dummy === null) {\n      var dummyJson = {\n        'tagName': 'div',\n        'attributes': [{\n          'name': 'id',\n          'value': 'textInputDummy'\n        }]\n      };\n\n      dummy = Common.buildDomElement(dummyJson);\n      document.body.appendChild(dummy);\n    }\n\n    function adjustInput() {\n      if (input.value === '') {\n        // If the input box is empty, remove the underline\n        input.classList.remove('underline');\n        input.setAttribute('style', 'width:' + '100%');\n        input.style.width = '100%';\n      } else {\n        // otherwise, adjust the dummy text to match, and then set the width of\n        // the visible input box to match it (thus extending the underline)\n        input.classList.add('underline');\n        var txtNode = document.createTextNode(input.value);\n        ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height',\n          'text-transform', 'letter-spacing'].forEach(function(index) {\n            dummy.style[index] = window.getComputedStyle(input, null).getPropertyValue(index);\n          });\n        dummy.textContent = txtNode.textContent;\n\n        var padding = 0;\n        var htmlElem = document.getElementsByTagName('html')[0];\n        var currentFontSize = parseInt(window.getComputedStyle(htmlElem, null).getPropertyValue('font-size'), 10);\n        if (currentFontSize) {\n          padding = Math.floor((currentFontSize - minFontSize) / (maxFontSize - minFontSize)\n            * (maxPadding - minPadding) + minPadding);\n        } else {\n          padding = maxPadding;\n        }\n\n        var widthValue = ( dummy.offsetWidth + padding) + 'px';\n        input.setAttribute('style', 'width:' + widthValue);\n        input.style.width = widthValue;\n      }\n    }\n\n    // Any time the input changes, or the window resizes, adjust the size of the input box\n    input.addEventListener('input', adjustInput);\n    window.addEventListener('resize', adjustInput);\n\n    // Trigger the input event once to set up the input box and dummy element\n    Common.fireEvent(input, 'input');\n  }\n\n  // Display a user or Watson message that has just been sent/received\n  function displayMessage(newPayload, typeValue) {\n    var isUser = isUserMessage(typeValue);\n    var textExists = (newPayload.input && newPayload.input.text)\n      || (newPayload.output && newPayload.output.text);\n    if (isUser !== null && textExists) {\n      // Create new message DOM element\n      var messageDivs = buildMessageDomElements(newPayload, isUser);\n      var chatBoxElement = document.querySelector(settings.selectors.chatBox);\n      var previousLatest = chatBoxElement.querySelectorAll((isUser\n              ? settings.selectors.fromUser : settings.selectors.fromWatson)\n              + settings.selectors.latest);\n      // Previous \"latest\" message is no longer the most recent\n      if (previousLatest) {\n        Common.listForEach(previousLatest, function(element) {\n          element.classList.remove('latest');\n        });\n      }\n\n      messageDivs.forEach(function(currentDiv) {\n        chatBoxElement.appendChild(currentDiv);\n        // Class to start fade in animation\n        currentDiv.classList.add('load');\n      });\n      // Move chat to the most recent messages when new messages are added\n      scrollToChatBottom();\n    }\n  }\n\n  // Checks if the given typeValue matches with the user \"name\", the Watson \"name\", or neither\n  // Returns true if user, false if Watson, and null if neither\n  // Used to keep track of whether a message was from the user or Watson\n  function isUserMessage(typeValue) {\n    if (typeValue === settings.authorTypes.user) {\n      return true;\n    } else if (typeValue === settings.authorTypes.watson) {\n      return false;\n    }\n    return null;\n  }\n\n  // Constructs new DOM element from a message payload\n  function buildMessageDomElements(newPayload, isUser) {\n    var textArray = isUser ? newPayload.input.text : newPayload.output.text;\n    if (Object.prototype.toString.call( textArray ) !== '[object Array]') {\n      textArray = [textArray];\n    }\n    var messageArray = [];\n\n    textArray.forEach(function(currentText) {\n      if (currentText) {\n        var messageJson = {\n          // <div class='segments'>\n          'tagName': 'div',\n          'classNames': ['segments'],\n          'children': [{\n            // <div class='from-user/from-watson latest'>\n            'tagName': 'div',\n            'classNames': [(isUser ? 'from-user' : 'from-watson'), 'latest', ((messageArray.length === 0) ? 'top' : 'sub')],\n            'children': [{\n              // <div class='message-inner'>\n              'tagName': 'div',\n              'classNames': ['message-inner'],\n              'children': [{\n                // <p>{messageText}</p>\n                'tagName': 'p',\n                'text': currentText\n              }]\n            }]\n          }]\n        };\n        messageArray.push(Common.buildDomElement(messageJson));\n      }\n    });\n\n    return messageArray;\n  }\n\n  // Scroll to the bottom of the chat window (to the most recent messages)\n  // Note: this method will bring the most recent user message into view,\n  //   even if the most recent message is from Watson.\n  //   This is done so that the \"context\" of the conversation is maintained in the view,\n  //   even if the Watson message is long.\n  function scrollToChatBottom() {\n    var scrollingChat = document.querySelector('#scrollingChat');\n\n    // Scroll to the latest message sent by the user\n    var scrollEl = scrollingChat.querySelector(settings.selectors.fromUser\n            + settings.selectors.latest);\n    if (scrollEl) {\n      scrollingChat.scrollTop = scrollEl.offsetTop;\n    }\n  }\n\n  // Handles the submission of input\n  function inputKeyDown(event, inputBox) {\n    // Submit on enter key, dis-allowing blank messages\n    if (event.keyCode === 13 && inputBox.value) {\n      // Retrieve the context from the previous server response\n      var context;\n      var latestResponse = Api.getResponsePayload();\n      if (latestResponse) {\n        context = latestResponse.context;\n      }\n\n      // Send the user message\n      Api.sendRequest(inputBox.value, context);\n\n      // Clear input box for further messages\n      inputBox.value = '';\n      Common.fireEvent(inputBox, 'input');\n    }\n  }\n}());\n"
  },
  {
    "path": "portal/public/res/js/global.js",
    "content": "\n/* global ConversationPanel: true, PayloadPanel: true*/\n/* eslint no-unused-vars: \"off\" */\n\n// Other JS files required to be loaded first: apis.js, conversation.js, payload.js\n(function() {\n  // Initialize all modules\n  ConversationPanel.init();\n  PayloadPanel.init();\n})();\n"
  },
  {
    "path": "portal/public/res/js/navbar.js",
    "content": "$(document).ready(function() {\n\t\n\t//Sticky navigation\n\tif (document.getElementById('js-section-features'))\n\t\t{\n\t\t\tvar waypoint = new Waypoint({\n\t\t\t  element: document.getElementById('js-section-features'),\n\t\t\t  handler: function(direction) {\n\t\t\t\tif (direction == \"down\") $('nav').addClass('sticky-nav')\n\t\t\t\telse $('nav').removeClass('sticky-nav')\n\t\t\t  }\n\t\t\t})\n\t\t}\n\t\n\t//Mobile navigation \n\t$('.mobile-nav-icon').click(function() {\n\t\t\n\t\tvar icon = $('.js-mobile-nav-icon')\n\t\t$('.main-nav').slideToggle(200)\n\t\t\n\t\tif (icon.hasClass('ion-navicon-round')) {\n\t\t\ticon.removeClass('ion-navicon-round');\n\t\t\ticon.addClass('ion-close-round')\n\t\t\t\n\t\t}\n\t\telse if (icon.hasClass('ion-close-round')) {\n\t\t\ticon.removeClass('ion-close-round');\n\t\t\ticon.addClass('ion-navicon-round')\n\t\t}\n\t\t\n\t})\n})"
  },
  {
    "path": "portal/public/res/js/payload.js",
    "content": "// The PayloadPanel module is designed to handle\n// all display and behaviors of the conversation column of the app.\n/* eslint no-unused-vars: \"off\" */\n/* global Api: true, Common: true, PayloadPanel: true*/\n\nvar PayloadPanel = (function() {\n  var settings = {\n    selectors: {\n      payloadColumn: '#payload-column',\n      payloadInitial: '#payload-initial-message',\n      payloadRequest: '#payload-request',\n      payloadResponse: '#payload-response'\n    },\n    payloadTypes: {\n      request: 'request',\n      response: 'response'\n    }\n  };\n\n  // Publicly accessible methods defined\n  return {\n    init: init,\n    togglePanel: togglePanel\n  };\n\n  // Initialize the module\n  function init() {\n    payloadUpdateSetup();\n  }\n\n  // Toggle panel between being:\n  // reduced width (default for large resolution apps)\n  // hidden (default for small/mobile resolution apps)\n  // full width (regardless of screen size)\n  function togglePanel(event, element) {\n    var payloadColumn = document.querySelector(settings.selectors.payloadColumn);\n    if (element.classList.contains('full')) {\n      element.classList.remove('full');\n      payloadColumn.classList.remove('full');\n    } else {\n      element.classList.add('full');\n      payloadColumn.classList.add('full');\n    }\n  }\n\n  // Set up callbacks on payload setters in Api module\n  // This causes the displayPayload function to be called when messages are sent / received\n  function payloadUpdateSetup() {\n    var currentRequestPayloadSetter = Api.setRequestPayload;\n    Api.setRequestPayload = function(newPayloadStr) {\n      currentRequestPayloadSetter.call(Api, newPayloadStr);\n      displayPayload(settings.payloadTypes.request);\n    };\n\n    var currentResponsePayloadSetter = Api.setResponsePayload;\n    Api.setResponsePayload = function(newPayload) {\n      currentResponsePayloadSetter.call(Api, newPayload);\n      displayPayload(settings.payloadTypes.response);\n    };\n  }\n\n  // Display a request or response payload that has just been sent/received\n  function displayPayload(typeValue) {\n    var isRequest = checkRequestType(typeValue);\n    if (isRequest !== null) {\n      // Create new payload DOM element\n      var payloadDiv = buildPayloadDomElement(isRequest);\n      var payloadElement = document.querySelector(isRequest\n              ? settings.selectors.payloadRequest : settings.selectors.payloadResponse);\n      // Clear out payload holder element\n      while (payloadElement.lastChild) {\n        payloadElement.removeChild(payloadElement.lastChild);\n      }\n      // Add new payload element\n      payloadElement.appendChild(payloadDiv);\n      // Set the horizontal rule to show (if request and response payloads both exist)\n      // or to hide (otherwise)\n      var payloadInitial = document.querySelector(settings.selectors.payloadInitial);\n      if (Api.getRequestPayload() || Api.getResponsePayload()) {\n        payloadInitial.classList.add('hide');\n      }\n    }\n  }\n\n  // Checks if the given typeValue matches with the request \"name\", the response \"name\", or neither\n  // Returns true if request, false if response, and null if neither\n  // Used to keep track of what type of payload we're currently working with\n  function checkRequestType(typeValue) {\n    if (typeValue === settings.payloadTypes.request) {\n      return true;\n    } else if (typeValue === settings.payloadTypes.response) {\n      return false;\n    }\n    return null;\n  }\n\n  // Constructs new DOM element to use in displaying the payload\n  function buildPayloadDomElement(isRequest) {\n    var payloadPrettyString = jsonPrettyPrint(isRequest\n            ? Api.getRequestPayload() : Api.getResponsePayload());\n\n    var payloadJson = {\n      'tagName': 'div',\n      'children': [{\n        // <div class='header-text'>\n        'tagName': 'div',\n        'text': isRequest ? 'User input' : 'Watson understands',\n        'classNames': ['header-text']\n      }, {\n        // <div class='code-line responsive-columns-wrapper'>\n        'tagName': 'div',\n        'classNames': ['code-line', 'responsive-columns-wrapper'],\n        'children': [{\n          // <div class='line-numbers'>\n          'tagName': 'pre',\n          'text': createLineNumberString((payloadPrettyString.match(/\\n/g) || []).length + 1),\n          'classNames': ['line-numbers']\n        }, {\n          // <div class='payload-text responsive-column'>\n          'tagName': 'pre',\n          'classNames': ['payload-text', 'responsive-column'],\n          'html': payloadPrettyString\n        }]\n      }]\n    };\n\n    return Common.buildDomElement(payloadJson);\n  }\n\n  // Format (payload) JSON to make it more readable\n  function jsonPrettyPrint(json) {\n    if (json === null) {\n      return '';\n    }\n    var convert = JSON.stringify(json, null, 2);\n\n    convert = convert.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(\n      />/g, '&gt;');\n    convert = convert\n      .replace(\n        /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g,\n        function(match) {\n          var cls = 'number';\n          if (/^\"/.test(match)) {\n            if (/:$/.test(match)) {\n              cls = 'key';\n            } else {\n              cls = 'string';\n            }\n          } else if (/true|false/.test(match)) {\n            cls = 'boolean';\n          } else if (/null/.test(match)) {\n            cls = 'null';\n          }\n          return '<span class=\"' + cls + '\">' + match + '</span>';\n        });\n    return convert;\n  }\n\n  // Used to generate a string of consecutive numbers separated by new lines\n  // - used as line numbers for displayed JSON\n  function createLineNumberString(numberOfLines) {\n    var lineString = '';\n    var prefix = '';\n    for (var i = 1; i <= numberOfLines; i++) {\n      lineString += prefix;\n      lineString += i;\n      prefix = '\\n';\n    }\n    return lineString;\n  }\n}());\n"
  },
  {
    "path": "portal/public/res/js/spending.js",
    "content": "$(document).ready(function() {\n\n  var http = new XMLHttpRequest();\n  var getUrl = window.location;\n  var baseUrl = getUrl.protocol + \"//\" + getUrl.host;\n  var transactionsEndpoint = baseUrl + '/endpoints/transactions/get';\n  console.log('Transactions >>>> ', transactionsEndpoint)\n  var uuid, total = 0;\n  var selectors = {\n    groceries: {\n        count: '#groceries_transaction_count',\n        total: '#groceries_transaction_total',\n        row: '#groceries_row',\n        link: '#groceries_link'\n    },\n    eating_out: {\n      count: '#eating_out_transaction_count',\n      total: '#eating_out_transaction_total',\n      row: '#eating_out_row',\n      link: '#eating_out_link'\n    },\n    transport: {\n      count: '#transport_transaction_count',\n      total: '#transport_transaction_total',\n      row: '#transport_row',\n      link: '#transport_link'\n    },\n    bills: {\n      count: '#bills_transaction_count',\n      total: '#bills_transaction_total',\n      row: '#bills_row',\n      link: '#bills_link'\n    },\n    expenses : {\n      count: '#expenses_transaction_count',\n      total: '#expenses_transaction_total',\n      row: '#expenses_row',\n      link: '#expenses_link'\n    },\n    cash : {\n      count: '#cash_transaction_count',\n      total: '#cash_transaction_total',\n      row: '#cash_row',\n      link: '#cash_link'\n    },\n    holidays : {\n      count: '#holidays_transaction_count',\n      total: '#holidays_transaction_total',\n      row: '#holidays_row',\n      link: '#holidays_link'\n    },\n  }\n\n  //Ensure authenticated and get uuid\n  http.open('GET', '/endpoints/auth', true);\n  http.setRequestHeader('Content-type', 'application/json');\n  http.onreadystatechange = function() {\n    if (http.readyState === 4 && http.status === 500) {\n      window.location.replace('/index.html')\n    }\n    else if (http.readyState === 4 && http.status === 200 && http.responseText) {\n      var response = JSON.parse(http.responseText)\n      console.log('response >>>> ', response)\n      uuid = response.uuid\n      http.open('POST', transactionsEndpoint, true);\n      http.setRequestHeader('Content-type', 'application/json');\n      http.onreadystatechange = function() {\n        if (http.readyState === 4 && http.status === 200 && http.responseText) {\n          console.log(http.responseText)\n          var transactions = JSON.parse(http.responseText).group(item => item.category);\n          console.log(transactions)\n          for (var selector in selectors) {\n            var transaction = transactions.find(item => item.key==selector)\n            if (transaction && transaction.total > 0) {\n              $(selectors[transaction.key].count).html(transaction.data.length + ' transactions');\n              $(selectors[transaction.key].total).html('AED ' + Math.round(transaction.total*100)/100);\n              total += transaction.total;\n            }\n            else {\n              $(selectors[selector].row).addClass('greyed-out')\n              $(selectors[selector].link).removeAttr('href')\n            }\n          }\n          $('#js-total').html(total)\n        }\n      };\n      http.send(JSON.stringify({'uuid': uuid}));\n    }\n  };\n  http.send();\n})\n\nObject.defineProperty(Array.prototype, 'group', {\n  enumerable: false,\n  value: function (key) {\n    let map = {};\n    this.map(e => ({k: key(e), d: e})).forEach(e => {\n      map[e.k] = map[e.k] || [];\n      if (e.d.amount) map[e.k].push(e.d);\n    });\n    return Object.keys(map).map(k => ({key: k, data: map[k], total: map[k].reduce(((a, b) => a + b.amount), 0)}));\n  }\n});\n"
  },
  {
    "path": "portal/public/res/js/transactions.js",
    "content": "$(document).ready(function() {\n\n  var http = new XMLHttpRequest();\n  var getUrl = window.location;\n  var baseUrl = getUrl.protocol + \"//\" + getUrl.host;\n  var transactionsEndpoint = baseUrl + '/endpoints/transactions/get';\n  console.log('Transactions >>>> ', transactionsEndpoint)\n  var uuid;\n  var innerHTML = '';\n  //Ensure authenticated and get uuid\n  http.open('GET', '/endpoints/auth', true);\n  http.setRequestHeader('Content-type', 'application/json');\n  http.onreadystatechange = function() {\n    if (http.readyState === 4 && http.status === 500) {\n      window.location.replace('/index.html')\n    }\n    else if (http.readyState === 4 && http.status === 200 && http.responseText) {\n      var response = JSON.parse(http.responseText)\n      console.log('response >>>> ', response)\n      uuid = response.uuid\n      http.open('POST', transactionsEndpoint, true);\n      http.setRequestHeader('Content-type', 'application/json');\n      http.onreadystatechange = function() {\n        if (http.readyState === 4 && http.status === 200 && http.responseText) {\n          var transactions = JSON.parse(http.responseText).group(item => item.category);\n          console.log(transactions)\n          transactions.forEach(function(category){\n            if (category.total > 0) {\n              innerHTML +=\n                `<div id=\"`+category.key+`\" class=\"row category\">` +\n                    `<h2>`+category.key.toTitleCase()+`</h2>` +\n                  `</div>`\n\n              category.data.forEach(function(transaction){\n                innerHTML +=\n                  `<div class=\"row transaction\">` +\n                      `<div class=\"col span-2-of-3\">` +\n                          `<h3>`+transaction.description+`</h3>` +\n                          `<p>`+transaction.date+`</p>` +\n                      `</div>` +\n                      `<div class=\"col span-1-of-3\">` +\n                          `<h3>AED `+transaction.amount+`</h3>` +\n                      `</div>` +\n                  `</div>`\n              })\n            }\n          })\n          $('#js-transaction-list').html(innerHTML)\n          console.log(innerHTML)\n        }\n      };\n      http.send(JSON.stringify({'uuid': uuid}));\n    }\n  };\n  http.send();\n})\n\nString.prototype.toTitleCase = function () {\n    return this.replace('_', ' ').replace(/\\w\\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()});\n};\n\nObject.defineProperty(Array.prototype, 'group', {\n  enumerable: false,\n  value: function (key) {\n    let map = {};\n    this.map(e => ({k: key(e), d: e})).forEach(e => {\n      map[e.k] = map[e.k] || [];\n      if (e.d.amount) map[e.k].push(e.d);\n    });\n    return Object.keys(map).map(k => ({key: k, data: map[k], total: map[k].reduce(((a, b) => a + b.amount), 0)}));\n  }\n});\n"
  },
  {
    "path": "portal/public/signup.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\t\t<header>\n\t\t\t<div class=\"col span-1-of-3 cutout\">\n\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t</div>\n\t\t\t<div class=\"col span-2-of-3 sign-up-box\">\n\t\t\t\t\t\t<section>\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>You're 60 seconds away from kick-ass banking</h2>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<form method=\"post\" action=\"endpoints/signup\" class=\"sign-up-form\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"name\">Name</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"name\" placeholder=\"Your name\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"email\">Email</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"email\" name=\"email\" id=\"email\" placeholder=\"Your email\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"phone\">Phone number</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"number\" name=\"phone\" id=\"phone\" placeholder=\"Your mobile phone number\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label>Gender</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<select name=\"gender\" id=\"gender\">\n\t\t\t\t\t\t\t\t<option value=\"male\" selected>Male</option>\n\t\t\t\t\t\t\t\t<option value=\"female\">Female</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"dob\">Date of birth</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"date\" name=\"dob\" id=\"dob\" placeholder=\"Your date of birth\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"eid\">Emirates Id number</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"number\" name=\"eid\" id=\"eid\" placeholder=\"Your EID\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col span-1-of-3\">\n\t\t\t\t\t\t\t<label for=\"password\">Password</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"col span-2-of-3\">\n\t\t\t\t\t\t\t<input type=\"password\" name=\"password\" id=\"password\" placeholder=\"Your password\" required>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row center\">\n\t\t\t\t\t\t<input type=\"checkbox\" name=\"tnc\" id=\"tnc\" required>\n\t\t\t\t\t\t\t<label for=\"tnc\">I agree to Terms and Conditions</label>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row\">\n\n\t\t\t\t\t\t<div class=\"col span-3-of-3\">\n\t\t\t\t\t\t\t<input type=\"submit\" value=\"Sign up!\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row center\">\n\t\t\t\t\t\t<div class=\"col span-3-of-3\">\n\t\t\t\t\t\t\tAlready have and account? <a href=\"login.html\">Log In</a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</section>\n\t\t\t</div>\n\t\t</header>\n\n\t\t<div id=\"unauthorized\" class=\"overlay\">\n\t\t\t<div class=\"popup\">\n\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t<a class=\"close\" href=\"#\">&times;</a>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\tYour username & password are incorrect. Try again, or contact support to recover lost login details.\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ion-ios-close icon-big\"></i>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/transactions.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/normalize.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/grid.css\">\n \t\t<link rel=\"stylesheet\" href=\"res/css/styles.css\">\n\t\t<link rel=\"stylesheet\" href=\"res/css/queries.css\">\n\t\t<link rel=\"stylesheet\" href=\"vendors/css/ionicons.min.css\">\n\t\t<link href=\"https://fonts.googleapis.com/css?family=Lato:100,300,300i,400\" rel=\"stylesheet\">\n\t\t<title>Innovate: Digital Bank</title>\n\t</head>\n\n\t<body>\n\n\t\t<header class=\"bar\">\n\t\t\t<nav>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<img src=\"res/img/logo-outline.png\" alt=\"Innovate logo\" class=\"logo\">\n\t\t\t\t\t<img src=\"res/img/logo.png\" alt=\"Innovatee logo\" class=\"logo-black\">\n\t\t\t\t\t<ul class=\"main-nav\">\n\t\t\t\t\t\t<li><a href=\"overview.html\">Spending</a></li>\n\t\t\t\t\t\t<li><a href=\"bills.html\">Bills</a></li>\n\t\t\t\t\t\t<li><a href=\"accounts.html\">Accounts</a></li>\n\t\t\t\t\t\t<li><a href=\"chat.html\">Support</a></li>\n\t\t\t\t\t\t<li><a href=\"/endpoints/logout\">Logout</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<a class=\"mobile-nav-icon\"><i class=\"js-mobile-nav-icon ion-navicon-round\"></i></a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t</header>\n\n\t\t<section class=\"section-spending\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<h2>Transactions</h2>\n\t\t\t</div>\n\t\t</section>\n\n\t\t<section id=\"js-transaction-list\" class=\"section-transaction-list\">\n\n\n\t\t</section>\n\n\t\t<footer>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"footer-nav\">\n\t\t\t\t\t\t<li><a href\"#\">About us</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Blog</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Press</a></li>\n\t\t\t\t\t\t<li><a href\"#\">iOS App</a></li>\n\t\t\t\t\t\t<li><a href\"#\">Android App</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col span-1-of-2\">\n\t\t\t\t\t<ul class=\"social-links\">\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-facebook\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-twitter\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-googleplus\"></i></a></li>\n\t\t\t\t\t\t<li><a href=\"#\"><i class=\"ion-social-instagram\"></i></a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<p>\n\t\t\t\t\tInnovate is a dummy digital bank created for demo purposes.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\n\t\t<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/respond/1.4.2/respond.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js\"></script>\n\t\t<script src=\"//cdn.jsdelivr.net/selectivizr/1.0.3b/selectivizr.min.js\"></script>\n\t\t<script src=\"vendors/js/noframework.waypoints.min.js\"></script>\n\t\t<script src=\"res/js/navbar.js\"></script>\n\t\t<script src=\"res/js/transactions.js\"></script>\n\n\t</body>\n\n</html>\n"
  },
  {
    "path": "portal/public/vendors/css/animate.css",
    "content": "@charset \"UTF-8\";\n\n/*!\nAnimate.css - http://daneden.me/animate\nLicensed under the MIT license - http://opensource.org/licenses/MIT\n\nCopyright (c) 2015 Daniel Eden\n*/\n\n.animated {\n  -webkit-animation-duration: 1s;\n  animation-duration: 1s;\n  -webkit-animation-fill-mode: both;\n  animation-fill-mode: both;\n}\n\n.animated.infinite {\n  -webkit-animation-iteration-count: infinite;\n  animation-iteration-count: infinite;\n}\n\n.animated.hinge {\n  -webkit-animation-duration: 2s;\n  animation-duration: 2s;\n}\n\n.animated.bounceIn,\n.animated.bounceOut {\n  -webkit-animation-duration: .75s;\n  animation-duration: .75s;\n}\n\n.animated.flipOutX,\n.animated.flipOutY {\n  -webkit-animation-duration: .75s;\n  animation-duration: .75s;\n}\n\n@-webkit-keyframes bounce {\n  0%, 20%, 53%, 80%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    -webkit-transform: translate3d(0,0,0);\n    transform: translate3d(0,0,0);\n  }\n\n  40%, 43% {\n    -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    -webkit-transform: translate3d(0, -30px, 0);\n    transform: translate3d(0, -30px, 0);\n  }\n\n  70% {\n    -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    -webkit-transform: translate3d(0, -15px, 0);\n    transform: translate3d(0, -15px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0,-4px,0);\n    transform: translate3d(0,-4px,0);\n  }\n}\n\n@keyframes bounce {\n  0%, 20%, 53%, 80%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    -webkit-transform: translate3d(0,0,0);\n    transform: translate3d(0,0,0);\n  }\n\n  40%, 43% {\n    -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    -webkit-transform: translate3d(0, -30px, 0);\n    transform: translate3d(0, -30px, 0);\n  }\n\n  70% {\n    -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);\n    -webkit-transform: translate3d(0, -15px, 0);\n    transform: translate3d(0, -15px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0,-4px,0);\n    transform: translate3d(0,-4px,0);\n  }\n}\n\n.bounce {\n  -webkit-animation-name: bounce;\n  animation-name: bounce;\n  -webkit-transform-origin: center bottom;\n  transform-origin: center bottom;\n}\n\n@-webkit-keyframes flash {\n  0%, 50%, 100% {\n    opacity: 1;\n  }\n\n  25%, 75% {\n    opacity: 0;\n  }\n}\n\n@keyframes flash {\n  0%, 50%, 100% {\n    opacity: 1;\n  }\n\n  25%, 75% {\n    opacity: 0;\n  }\n}\n\n.flash {\n  -webkit-animation-name: flash;\n  animation-name: flash;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes pulse {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  50% {\n    -webkit-transform: scale3d(1.05, 1.05, 1.05);\n    transform: scale3d(1.05, 1.05, 1.05);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n@keyframes pulse {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  50% {\n    -webkit-transform: scale3d(1.05, 1.05, 1.05);\n    transform: scale3d(1.05, 1.05, 1.05);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n.pulse {\n  -webkit-animation-name: pulse;\n  animation-name: pulse;\n}\n\n@-webkit-keyframes rubberBand {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  30% {\n    -webkit-transform: scale3d(1.25, 0.75, 1);\n    transform: scale3d(1.25, 0.75, 1);\n  }\n\n  40% {\n    -webkit-transform: scale3d(0.75, 1.25, 1);\n    transform: scale3d(0.75, 1.25, 1);\n  }\n\n  50% {\n    -webkit-transform: scale3d(1.15, 0.85, 1);\n    transform: scale3d(1.15, 0.85, 1);\n  }\n\n  65% {\n    -webkit-transform: scale3d(.95, 1.05, 1);\n    transform: scale3d(.95, 1.05, 1);\n  }\n\n  75% {\n    -webkit-transform: scale3d(1.05, .95, 1);\n    transform: scale3d(1.05, .95, 1);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n@keyframes rubberBand {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  30% {\n    -webkit-transform: scale3d(1.25, 0.75, 1);\n    transform: scale3d(1.25, 0.75, 1);\n  }\n\n  40% {\n    -webkit-transform: scale3d(0.75, 1.25, 1);\n    transform: scale3d(0.75, 1.25, 1);\n  }\n\n  50% {\n    -webkit-transform: scale3d(1.15, 0.85, 1);\n    transform: scale3d(1.15, 0.85, 1);\n  }\n\n  65% {\n    -webkit-transform: scale3d(.95, 1.05, 1);\n    transform: scale3d(.95, 1.05, 1);\n  }\n\n  75% {\n    -webkit-transform: scale3d(1.05, .95, 1);\n    transform: scale3d(1.05, .95, 1);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n.rubberBand {\n  -webkit-animation-name: rubberBand;\n  animation-name: rubberBand;\n}\n\n@-webkit-keyframes shake {\n  0%, 100% {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n  }\n\n  10%, 30%, 50%, 70%, 90% {\n    -webkit-transform: translate3d(-10px, 0, 0);\n    transform: translate3d(-10px, 0, 0);\n  }\n\n  20%, 40%, 60%, 80% {\n    -webkit-transform: translate3d(10px, 0, 0);\n    transform: translate3d(10px, 0, 0);\n  }\n}\n\n@keyframes shake {\n  0%, 100% {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n  }\n\n  10%, 30%, 50%, 70%, 90% {\n    -webkit-transform: translate3d(-10px, 0, 0);\n    transform: translate3d(-10px, 0, 0);\n  }\n\n  20%, 40%, 60%, 80% {\n    -webkit-transform: translate3d(10px, 0, 0);\n    transform: translate3d(10px, 0, 0);\n  }\n}\n\n.shake {\n  -webkit-animation-name: shake;\n  animation-name: shake;\n}\n\n@-webkit-keyframes swing {\n  20% {\n    -webkit-transform: rotate3d(0, 0, 1, 15deg);\n    transform: rotate3d(0, 0, 1, 15deg);\n  }\n\n  40% {\n    -webkit-transform: rotate3d(0, 0, 1, -10deg);\n    transform: rotate3d(0, 0, 1, -10deg);\n  }\n\n  60% {\n    -webkit-transform: rotate3d(0, 0, 1, 5deg);\n    transform: rotate3d(0, 0, 1, 5deg);\n  }\n\n  80% {\n    -webkit-transform: rotate3d(0, 0, 1, -5deg);\n    transform: rotate3d(0, 0, 1, -5deg);\n  }\n\n  100% {\n    -webkit-transform: rotate3d(0, 0, 1, 0deg);\n    transform: rotate3d(0, 0, 1, 0deg);\n  }\n}\n\n@keyframes swing {\n  20% {\n    -webkit-transform: rotate3d(0, 0, 1, 15deg);\n    transform: rotate3d(0, 0, 1, 15deg);\n  }\n\n  40% {\n    -webkit-transform: rotate3d(0, 0, 1, -10deg);\n    transform: rotate3d(0, 0, 1, -10deg);\n  }\n\n  60% {\n    -webkit-transform: rotate3d(0, 0, 1, 5deg);\n    transform: rotate3d(0, 0, 1, 5deg);\n  }\n\n  80% {\n    -webkit-transform: rotate3d(0, 0, 1, -5deg);\n    transform: rotate3d(0, 0, 1, -5deg);\n  }\n\n  100% {\n    -webkit-transform: rotate3d(0, 0, 1, 0deg);\n    transform: rotate3d(0, 0, 1, 0deg);\n  }\n}\n\n.swing {\n  -webkit-transform-origin: top center;\n  transform-origin: top center;\n  -webkit-animation-name: swing;\n  animation-name: swing;\n}\n\n@-webkit-keyframes tada {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  10%, 20% {\n    -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);\n    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);\n  }\n\n  30%, 50%, 70%, 90% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);\n    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);\n  }\n\n  40%, 60%, 80% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);\n    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n@keyframes tada {\n  0% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n\n  10%, 20% {\n    -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);\n    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);\n  }\n\n  30%, 50%, 70%, 90% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);\n    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);\n  }\n\n  40%, 60%, 80% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);\n    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);\n  }\n\n  100% {\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n.tada {\n  -webkit-animation-name: tada;\n  animation-name: tada;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes wobble {\n  0% {\n    -webkit-transform: none;\n    transform: none;\n  }\n\n  15% {\n    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);\n    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);\n  }\n\n  30% {\n    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);\n    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);\n  }\n\n  45% {\n    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);\n    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);\n  }\n\n  60% {\n    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);\n    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);\n  }\n\n  75% {\n    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);\n    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes wobble {\n  0% {\n    -webkit-transform: none;\n    transform: none;\n  }\n\n  15% {\n    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);\n    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);\n  }\n\n  30% {\n    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);\n    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);\n  }\n\n  45% {\n    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);\n    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);\n  }\n\n  60% {\n    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);\n    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);\n  }\n\n  75% {\n    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);\n    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.wobble {\n  -webkit-animation-name: wobble;\n  animation-name: wobble;\n}\n\n@-webkit-keyframes bounceIn {\n  0%, 20%, 40%, 60%, 80%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  20% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1);\n    transform: scale3d(1.1, 1.1, 1.1);\n  }\n\n  40% {\n    -webkit-transform: scale3d(.9, .9, .9);\n    transform: scale3d(.9, .9, .9);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(1.03, 1.03, 1.03);\n    transform: scale3d(1.03, 1.03, 1.03);\n  }\n\n  80% {\n    -webkit-transform: scale3d(.97, .97, .97);\n    transform: scale3d(.97, .97, .97);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n@keyframes bounceIn {\n  0%, 20%, 40%, 60%, 80%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  20% {\n    -webkit-transform: scale3d(1.1, 1.1, 1.1);\n    transform: scale3d(1.1, 1.1, 1.1);\n  }\n\n  40% {\n    -webkit-transform: scale3d(.9, .9, .9);\n    transform: scale3d(.9, .9, .9);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(1.03, 1.03, 1.03);\n    transform: scale3d(1.03, 1.03, 1.03);\n  }\n\n  80% {\n    -webkit-transform: scale3d(.97, .97, .97);\n    transform: scale3d(.97, .97, .97);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: scale3d(1, 1, 1);\n    transform: scale3d(1, 1, 1);\n  }\n}\n\n.bounceIn {\n  -webkit-animation-name: bounceIn;\n  animation-name: bounceIn;\n}\n\n@-webkit-keyframes bounceInDown {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -3000px, 0);\n    transform: translate3d(0, -3000px, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, 25px, 0);\n    transform: translate3d(0, 25px, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(0, -10px, 0);\n    transform: translate3d(0, -10px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0, 5px, 0);\n    transform: translate3d(0, 5px, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes bounceInDown {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -3000px, 0);\n    transform: translate3d(0, -3000px, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, 25px, 0);\n    transform: translate3d(0, 25px, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(0, -10px, 0);\n    transform: translate3d(0, -10px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0, 5px, 0);\n    transform: translate3d(0, 5px, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.bounceInDown {\n  -webkit-animation-name: bounceInDown;\n  animation-name: bounceInDown;\n}\n\n@-webkit-keyframes bounceInLeft {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-3000px, 0, 0);\n    transform: translate3d(-3000px, 0, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(25px, 0, 0);\n    transform: translate3d(25px, 0, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(-10px, 0, 0);\n    transform: translate3d(-10px, 0, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(5px, 0, 0);\n    transform: translate3d(5px, 0, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes bounceInLeft {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-3000px, 0, 0);\n    transform: translate3d(-3000px, 0, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(25px, 0, 0);\n    transform: translate3d(25px, 0, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(-10px, 0, 0);\n    transform: translate3d(-10px, 0, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(5px, 0, 0);\n    transform: translate3d(5px, 0, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.bounceInLeft {\n  -webkit-animation-name: bounceInLeft;\n  animation-name: bounceInLeft;\n}\n\n@-webkit-keyframes bounceInRight {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(3000px, 0, 0);\n    transform: translate3d(3000px, 0, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(-25px, 0, 0);\n    transform: translate3d(-25px, 0, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(10px, 0, 0);\n    transform: translate3d(10px, 0, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(-5px, 0, 0);\n    transform: translate3d(-5px, 0, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes bounceInRight {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(3000px, 0, 0);\n    transform: translate3d(3000px, 0, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(-25px, 0, 0);\n    transform: translate3d(-25px, 0, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(10px, 0, 0);\n    transform: translate3d(10px, 0, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(-5px, 0, 0);\n    transform: translate3d(-5px, 0, 0);\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.bounceInRight {\n  -webkit-animation-name: bounceInRight;\n  animation-name: bounceInRight;\n}\n\n@-webkit-keyframes bounceInUp {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 3000px, 0);\n    transform: translate3d(0, 3000px, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, -20px, 0);\n    transform: translate3d(0, -20px, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(0, 10px, 0);\n    transform: translate3d(0, 10px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0, -5px, 0);\n    transform: translate3d(0, -5px, 0);\n  }\n\n  100% {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n  }\n}\n\n@keyframes bounceInUp {\n  0%, 60%, 75%, 90%, 100% {\n    -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);\n  }\n\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 3000px, 0);\n    transform: translate3d(0, 3000px, 0);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, -20px, 0);\n    transform: translate3d(0, -20px, 0);\n  }\n\n  75% {\n    -webkit-transform: translate3d(0, 10px, 0);\n    transform: translate3d(0, 10px, 0);\n  }\n\n  90% {\n    -webkit-transform: translate3d(0, -5px, 0);\n    transform: translate3d(0, -5px, 0);\n  }\n\n  100% {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n  }\n}\n\n.bounceInUp {\n  -webkit-animation-name: bounceInUp;\n  animation-name: bounceInUp;\n}\n\n@-webkit-keyframes bounceOut {\n  20% {\n    -webkit-transform: scale3d(.9, .9, .9);\n    transform: scale3d(.9, .9, .9);\n  }\n\n  50%, 55% {\n    opacity: 1;\n    -webkit-transform: scale3d(1.1, 1.1, 1.1);\n    transform: scale3d(1.1, 1.1, 1.1);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n}\n\n@keyframes bounceOut {\n  20% {\n    -webkit-transform: scale3d(.9, .9, .9);\n    transform: scale3d(.9, .9, .9);\n  }\n\n  50%, 55% {\n    opacity: 1;\n    -webkit-transform: scale3d(1.1, 1.1, 1.1);\n    transform: scale3d(1.1, 1.1, 1.1);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n}\n\n.bounceOut {\n  -webkit-animation-name: bounceOut;\n  animation-name: bounceOut;\n}\n\n@-webkit-keyframes bounceOutDown {\n  20% {\n    -webkit-transform: translate3d(0, 10px, 0);\n    transform: translate3d(0, 10px, 0);\n  }\n\n  40%, 45% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, -20px, 0);\n    transform: translate3d(0, -20px, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n}\n\n@keyframes bounceOutDown {\n  20% {\n    -webkit-transform: translate3d(0, 10px, 0);\n    transform: translate3d(0, 10px, 0);\n  }\n\n  40%, 45% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, -20px, 0);\n    transform: translate3d(0, -20px, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n}\n\n.bounceOutDown {\n  -webkit-animation-name: bounceOutDown;\n  animation-name: bounceOutDown;\n}\n\n@-webkit-keyframes bounceOutLeft {\n  20% {\n    opacity: 1;\n    -webkit-transform: translate3d(20px, 0, 0);\n    transform: translate3d(20px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n}\n\n@keyframes bounceOutLeft {\n  20% {\n    opacity: 1;\n    -webkit-transform: translate3d(20px, 0, 0);\n    transform: translate3d(20px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n}\n\n.bounceOutLeft {\n  -webkit-animation-name: bounceOutLeft;\n  animation-name: bounceOutLeft;\n}\n\n@-webkit-keyframes bounceOutRight {\n  20% {\n    opacity: 1;\n    -webkit-transform: translate3d(-20px, 0, 0);\n    transform: translate3d(-20px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n}\n\n@keyframes bounceOutRight {\n  20% {\n    opacity: 1;\n    -webkit-transform: translate3d(-20px, 0, 0);\n    transform: translate3d(-20px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n}\n\n.bounceOutRight {\n  -webkit-animation-name: bounceOutRight;\n  animation-name: bounceOutRight;\n}\n\n@-webkit-keyframes bounceOutUp {\n  20% {\n    -webkit-transform: translate3d(0, -10px, 0);\n    transform: translate3d(0, -10px, 0);\n  }\n\n  40%, 45% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, 20px, 0);\n    transform: translate3d(0, 20px, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n}\n\n@keyframes bounceOutUp {\n  20% {\n    -webkit-transform: translate3d(0, -10px, 0);\n    transform: translate3d(0, -10px, 0);\n  }\n\n  40%, 45% {\n    opacity: 1;\n    -webkit-transform: translate3d(0, 20px, 0);\n    transform: translate3d(0, 20px, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n}\n\n.bounceOutUp {\n  -webkit-animation-name: bounceOutUp;\n  animation-name: bounceOutUp;\n}\n\n@-webkit-keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n.fadeIn {\n  -webkit-animation-name: fadeIn;\n  animation-name: fadeIn;\n}\n\n@-webkit-keyframes fadeInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -100%, 0);\n    transform: translate3d(0, -100%, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -100%, 0);\n    transform: translate3d(0, -100%, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInDown {\n  -webkit-animation-name: fadeInDown;\n  animation-name: fadeInDown;\n}\n\n@-webkit-keyframes fadeInDownBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInDownBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInDownBig {\n  -webkit-animation-name: fadeInDownBig;\n  animation-name: fadeInDownBig;\n}\n\n@-webkit-keyframes fadeInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInLeft {\n  -webkit-animation-name: fadeInLeft;\n  animation-name: fadeInLeft;\n}\n\n@-webkit-keyframes fadeInLeftBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInLeftBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInLeftBig {\n  -webkit-animation-name: fadeInLeftBig;\n  animation-name: fadeInLeftBig;\n}\n\n@-webkit-keyframes fadeInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInRight {\n  -webkit-animation-name: fadeInRight;\n  animation-name: fadeInRight;\n}\n\n@-webkit-keyframes fadeInRightBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInRightBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInRightBig {\n  -webkit-animation-name: fadeInRightBig;\n  animation-name: fadeInRightBig;\n}\n\n@-webkit-keyframes fadeInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 100%, 0);\n    transform: translate3d(0, 100%, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 100%, 0);\n    transform: translate3d(0, 100%, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInUp {\n  -webkit-animation-name: fadeInUp;\n  animation-name: fadeInUp;\n}\n\n@-webkit-keyframes fadeInUpBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes fadeInUpBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.fadeInUpBig {\n  -webkit-animation-name: fadeInUpBig;\n  animation-name: fadeInUpBig;\n}\n\n@-webkit-keyframes fadeOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n@keyframes fadeOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n.fadeOut {\n  -webkit-animation-name: fadeOut;\n  animation-name: fadeOut;\n}\n\n@-webkit-keyframes fadeOutDown {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 100%, 0);\n    transform: translate3d(0, 100%, 0);\n  }\n}\n\n@keyframes fadeOutDown {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 100%, 0);\n    transform: translate3d(0, 100%, 0);\n  }\n}\n\n.fadeOutDown {\n  -webkit-animation-name: fadeOutDown;\n  animation-name: fadeOutDown;\n}\n\n@-webkit-keyframes fadeOutDownBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n}\n\n@keyframes fadeOutDownBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, 2000px, 0);\n    transform: translate3d(0, 2000px, 0);\n  }\n}\n\n.fadeOutDownBig {\n  -webkit-animation-name: fadeOutDownBig;\n  animation-name: fadeOutDownBig;\n}\n\n@-webkit-keyframes fadeOutLeft {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0);\n  }\n}\n\n@keyframes fadeOutLeft {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0);\n  }\n}\n\n.fadeOutLeft {\n  -webkit-animation-name: fadeOutLeft;\n  animation-name: fadeOutLeft;\n}\n\n@-webkit-keyframes fadeOutLeftBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n}\n\n@keyframes fadeOutLeftBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(-2000px, 0, 0);\n    transform: translate3d(-2000px, 0, 0);\n  }\n}\n\n.fadeOutLeftBig {\n  -webkit-animation-name: fadeOutLeftBig;\n  animation-name: fadeOutLeftBig;\n}\n\n@-webkit-keyframes fadeOutRight {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0);\n  }\n}\n\n@keyframes fadeOutRight {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0);\n  }\n}\n\n.fadeOutRight {\n  -webkit-animation-name: fadeOutRight;\n  animation-name: fadeOutRight;\n}\n\n@-webkit-keyframes fadeOutRightBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n}\n\n@keyframes fadeOutRightBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(2000px, 0, 0);\n    transform: translate3d(2000px, 0, 0);\n  }\n}\n\n.fadeOutRightBig {\n  -webkit-animation-name: fadeOutRightBig;\n  animation-name: fadeOutRightBig;\n}\n\n@-webkit-keyframes fadeOutUp {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -100%, 0);\n    transform: translate3d(0, -100%, 0);\n  }\n}\n\n@keyframes fadeOutUp {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -100%, 0);\n    transform: translate3d(0, -100%, 0);\n  }\n}\n\n.fadeOutUp {\n  -webkit-animation-name: fadeOutUp;\n  animation-name: fadeOutUp;\n}\n\n@-webkit-keyframes fadeOutUpBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n}\n\n@keyframes fadeOutUpBig {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(0, -2000px, 0);\n    transform: translate3d(0, -2000px, 0);\n  }\n}\n\n.fadeOutUpBig {\n  -webkit-animation-name: fadeOutUpBig;\n  animation-name: fadeOutUpBig;\n}\n\n@-webkit-keyframes flip {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -360deg);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);\n    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  50% {\n    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);\n    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) scale3d(.95, .95, .95);\n    transform: perspective(400px) scale3d(.95, .95, .95);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n}\n\n@keyframes flip {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -360deg);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);\n    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  50% {\n    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);\n    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) scale3d(.95, .95, .95);\n    transform: perspective(400px) scale3d(.95, .95, .95);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n}\n\n.animated.flip {\n  -webkit-backface-visibility: visible;\n  backface-visibility: visible;\n  -webkit-animation-name: flip;\n  animation-name: flip;\n}\n\n@-webkit-keyframes flipInX {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n  }\n\n  60% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n}\n\n@keyframes flipInX {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n  }\n\n  60% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n}\n\n.flipInX {\n  -webkit-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipInX;\n  animation-name: flipInX;\n}\n\n@-webkit-keyframes flipInY {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n  }\n\n  60% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n}\n\n@keyframes flipInY {\n  0% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);\n    -webkit-transition-timing-function: ease-in;\n    transition-timing-function: ease-in;\n  }\n\n  60% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n}\n\n.flipInY {\n  -webkit-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipInY;\n  animation-name: flipInY;\n}\n\n@-webkit-keyframes flipOutX {\n  0% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n\n  30% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes flipOutX {\n  0% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n\n  30% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);\n    opacity: 0;\n  }\n}\n\n.flipOutX {\n  -webkit-animation-name: flipOutX;\n  animation-name: flipOutX;\n  -webkit-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n}\n\n@-webkit-keyframes flipOutY {\n  0% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n\n  30% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes flipOutY {\n  0% {\n    -webkit-transform: perspective(400px);\n    transform: perspective(400px);\n  }\n\n  30% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);\n    opacity: 0;\n  }\n}\n\n.flipOutY {\n  -webkit-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipOutY;\n  animation-name: flipOutY;\n}\n\n@-webkit-keyframes lightSpeedIn {\n  0% {\n    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);\n    transform: translate3d(100%, 0, 0) skewX(-30deg);\n    opacity: 0;\n  }\n\n  60% {\n    -webkit-transform: skewX(20deg);\n    transform: skewX(20deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: skewX(-5deg);\n    transform: skewX(-5deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes lightSpeedIn {\n  0% {\n    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);\n    transform: translate3d(100%, 0, 0) skewX(-30deg);\n    opacity: 0;\n  }\n\n  60% {\n    -webkit-transform: skewX(20deg);\n    transform: skewX(20deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: skewX(-5deg);\n    transform: skewX(-5deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.lightSpeedIn {\n  -webkit-animation-name: lightSpeedIn;\n  animation-name: lightSpeedIn;\n  -webkit-animation-timing-function: ease-out;\n  animation-timing-function: ease-out;\n}\n\n@-webkit-keyframes lightSpeedOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);\n    transform: translate3d(100%, 0, 0) skewX(30deg);\n    opacity: 0;\n  }\n}\n\n@keyframes lightSpeedOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);\n    transform: translate3d(100%, 0, 0) skewX(30deg);\n    opacity: 0;\n  }\n}\n\n.lightSpeedOut {\n  -webkit-animation-name: lightSpeedOut;\n  animation-name: lightSpeedOut;\n  -webkit-animation-timing-function: ease-in;\n  animation-timing-function: ease-in;\n}\n\n@-webkit-keyframes rotateIn {\n  0% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: rotate3d(0, 0, 1, -200deg);\n    transform: rotate3d(0, 0, 1, -200deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes rotateIn {\n  0% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: rotate3d(0, 0, 1, -200deg);\n    transform: rotate3d(0, 0, 1, -200deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.rotateIn {\n  -webkit-animation-name: rotateIn;\n  animation-name: rotateIn;\n}\n\n@-webkit-keyframes rotateInDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.rotateInDownLeft {\n  -webkit-animation-name: rotateInDownLeft;\n  animation-name: rotateInDownLeft;\n}\n\n@-webkit-keyframes rotateInDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.rotateInDownRight {\n  -webkit-animation-name: rotateInDownRight;\n  animation-name: rotateInDownRight;\n}\n\n@-webkit-keyframes rotateInUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.rotateInUpLeft {\n  -webkit-animation-name: rotateInUpLeft;\n  animation-name: rotateInUpLeft;\n}\n\n@-webkit-keyframes rotateInUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -90deg);\n    transform: rotate3d(0, 0, 1, -90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -90deg);\n    transform: rotate3d(0, 0, 1, -90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: none;\n    transform: none;\n    opacity: 1;\n  }\n}\n\n.rotateInUpRight {\n  -webkit-animation-name: rotateInUpRight;\n  animation-name: rotateInUpRight;\n}\n\n@-webkit-keyframes rotateOut {\n  0% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: rotate3d(0, 0, 1, 200deg);\n    transform: rotate3d(0, 0, 1, 200deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOut {\n  0% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: center;\n    transform-origin: center;\n    -webkit-transform: rotate3d(0, 0, 1, 200deg);\n    transform: rotate3d(0, 0, 1, 200deg);\n    opacity: 0;\n  }\n}\n\n.rotateOut {\n  -webkit-animation-name: rotateOut;\n  animation-name: rotateOut;\n}\n\n@-webkit-keyframes rotateOutDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 45deg);\n    transform: rotate3d(0, 0, 1, 45deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutDownLeft {\n  -webkit-animation-name: rotateOutDownLeft;\n  animation-name: rotateOutDownLeft;\n}\n\n@-webkit-keyframes rotateOutDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutDownRight {\n  -webkit-animation-name: rotateOutDownRight;\n  animation-name: rotateOutDownRight;\n}\n\n@-webkit-keyframes rotateOutUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate3d(0, 0, 1, -45deg);\n    transform: rotate3d(0, 0, 1, -45deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutUpLeft {\n  -webkit-animation-name: rotateOutUpLeft;\n  animation-name: rotateOutUpLeft;\n}\n\n@-webkit-keyframes rotateOutUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 90deg);\n    transform: rotate3d(0, 0, 1, 90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate3d(0, 0, 1, 90deg);\n    transform: rotate3d(0, 0, 1, 90deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutUpRight {\n  -webkit-animation-name: rotateOutUpRight;\n  animation-name: rotateOutUpRight;\n}\n\n@-webkit-keyframes hinge {\n  0% {\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  20%, 60% {\n    -webkit-transform: rotate3d(0, 0, 1, 80deg);\n    transform: rotate3d(0, 0, 1, 80deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  40%, 80% {\n    -webkit-transform: rotate3d(0, 0, 1, 60deg);\n    transform: rotate3d(0, 0, 1, 60deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translate3d(0, 700px, 0);\n    transform: translate3d(0, 700px, 0);\n    opacity: 0;\n  }\n}\n\n@keyframes hinge {\n  0% {\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  20%, 60% {\n    -webkit-transform: rotate3d(0, 0, 1, 80deg);\n    transform: rotate3d(0, 0, 1, 80deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  40%, 80% {\n    -webkit-transform: rotate3d(0, 0, 1, 60deg);\n    transform: rotate3d(0, 0, 1, 60deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translate3d(0, 700px, 0);\n    transform: translate3d(0, 700px, 0);\n    opacity: 0;\n  }\n}\n\n.hinge {\n  -webkit-animation-name: hinge;\n  animation-name: hinge;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);\n    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes rollIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);\n    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.rollIn {\n  -webkit-animation-name: rollIn;\n  animation-name: rollIn;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);\n    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);\n  }\n}\n\n@keyframes rollOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);\n    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);\n  }\n}\n\n.rollOut {\n  -webkit-animation-name: rollOut;\n  animation-name: rollOut;\n}\n\n@-webkit-keyframes zoomIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  50% {\n    opacity: 1;\n  }\n}\n\n@keyframes zoomIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  50% {\n    opacity: 1;\n  }\n}\n\n.zoomIn {\n  -webkit-animation-name: zoomIn;\n  animation-name: zoomIn;\n}\n\n@-webkit-keyframes zoomInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomInDown {\n  -webkit-animation-name: zoomInDown;\n  animation-name: zoomInDown;\n}\n\n@-webkit-keyframes zoomInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);\n    transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);\n    transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomInLeft {\n  -webkit-animation-name: zoomInLeft;\n  animation-name: zoomInLeft;\n}\n\n@-webkit-keyframes zoomInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);\n    transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);\n    transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomInRight {\n  -webkit-animation-name: zoomInRight;\n  animation-name: zoomInRight;\n}\n\n@-webkit-keyframes zoomInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomInUp {\n  -webkit-animation-name: zoomInUp;\n  animation-name: zoomInUp;\n}\n\n@-webkit-keyframes zoomOut {\n  0% {\n    opacity: 1;\n  }\n\n  50% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n@keyframes zoomOut {\n  0% {\n    opacity: 1;\n  }\n\n  50% {\n    opacity: 0;\n    -webkit-transform: scale3d(.3, .3, .3);\n    transform: scale3d(.3, .3, .3);\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n.zoomOut {\n  -webkit-animation-name: zoomOut;\n  animation-name: zoomOut;\n}\n\n@-webkit-keyframes zoomOutDown {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);\n    -webkit-transform-origin: center bottom;\n    transform-origin: center bottom;\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomOutDown {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);\n    -webkit-transform-origin: center bottom;\n    transform-origin: center bottom;\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomOutDown {\n  -webkit-animation-name: zoomOutDown;\n  animation-name: zoomOutDown;\n}\n\n@-webkit-keyframes zoomOutLeft {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);\n    transform: scale(.1) translate3d(-2000px, 0, 0);\n    -webkit-transform-origin: left center;\n    transform-origin: left center;\n  }\n}\n\n@keyframes zoomOutLeft {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);\n    transform: scale(.1) translate3d(-2000px, 0, 0);\n    -webkit-transform-origin: left center;\n    transform-origin: left center;\n  }\n}\n\n.zoomOutLeft {\n  -webkit-animation-name: zoomOutLeft;\n  animation-name: zoomOutLeft;\n}\n\n@-webkit-keyframes zoomOutRight {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.1) translate3d(2000px, 0, 0);\n    transform: scale(.1) translate3d(2000px, 0, 0);\n    -webkit-transform-origin: right center;\n    transform-origin: right center;\n  }\n}\n\n@keyframes zoomOutRight {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);\n    transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.1) translate3d(2000px, 0, 0);\n    transform: scale(.1) translate3d(2000px, 0, 0);\n    -webkit-transform-origin: right center;\n    transform-origin: right center;\n  }\n}\n\n.zoomOutRight {\n  -webkit-animation-name: zoomOutRight;\n  animation-name: zoomOutRight;\n}\n\n@-webkit-keyframes zoomOutUp {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);\n    -webkit-transform-origin: center bottom;\n    transform-origin: center bottom;\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n@keyframes zoomOutUp {\n  40% {\n    opacity: 1;\n    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);\n    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);\n    transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);\n    -webkit-transform-origin: center bottom;\n    transform-origin: center bottom;\n    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);\n  }\n}\n\n.zoomOutUp {\n  -webkit-animation-name: zoomOutUp;\n  animation-name: zoomOutUp;\n}\n\n@-webkit-keyframes slideInDown {\n  0% {\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes slideInDown {\n  0% {\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.slideInDown {\n  -webkit-animation-name: slideInDown;\n  animation-name: slideInDown;\n}\n\n@-webkit-keyframes slideInLeft {\n  0% {\n    -webkit-transform: translateX(-100%);\n    transform: translateX(-100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes slideInLeft {\n  0% {\n    -webkit-transform: translateX(-100%);\n    transform: translateX(-100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.slideInLeft {\n  -webkit-animation-name: slideInLeft;\n  animation-name: slideInLeft;\n}\n\n@-webkit-keyframes slideInRight {\n  0% {\n    -webkit-transform: translateX(100%);\n    transform: translateX(100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes slideInRight {\n  0% {\n    -webkit-transform: translateX(100%);\n    transform: translateX(100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.slideInRight {\n  -webkit-animation-name: slideInRight;\n  animation-name: slideInRight;\n}\n\n@-webkit-keyframes slideInUp {\n  0% {\n    -webkit-transform: translateY(100%);\n    transform: translateY(100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes slideInUp {\n  0% {\n    -webkit-transform: translateY(100%);\n    transform: translateY(100%);\n    visibility: visible;\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.slideInUp {\n  -webkit-animation-name: slideInUp;\n  animation-name: slideInUp;\n}\n\n@-webkit-keyframes slideOutDown {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateY(100%);\n    transform: translateY(100%);\n  }\n}\n\n@keyframes slideOutDown {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateY(100%);\n    transform: translateY(100%);\n  }\n}\n\n.slideOutDown {\n  -webkit-animation-name: slideOutDown;\n  animation-name: slideOutDown;\n}\n\n@-webkit-keyframes slideOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateX(-100%);\n    transform: translateX(-100%);\n  }\n}\n\n@keyframes slideOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateX(-100%);\n    transform: translateX(-100%);\n  }\n}\n\n.slideOutLeft {\n  -webkit-animation-name: slideOutLeft;\n  animation-name: slideOutLeft;\n}\n\n@-webkit-keyframes slideOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateX(100%);\n    transform: translateX(100%);\n  }\n}\n\n@keyframes slideOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateX(100%);\n    transform: translateX(100%);\n  }\n}\n\n.slideOutRight {\n  -webkit-animation-name: slideOutRight;\n  animation-name: slideOutRight;\n}\n\n@-webkit-keyframes slideOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n  }\n}\n\n@keyframes slideOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    visibility: hidden;\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n  }\n}\n\n.slideOutUp {\n  -webkit-animation-name: slideOutUp;\n  animation-name: slideOutUp;\n}"
  },
  {
    "path": "portal/public/vendors/css/grid.css",
    "content": "\n/*  SECTIONS  ============================================================================= */\n\n.section {\n\tclear: both;\n\tpadding: 0px;\n\tmargin: 0px;\n}\n\n/*  GROUPING  ============================================================================= */\n\n.row {\n    zoom: 1; /* For IE 6/7 (trigger hasLayout) */\n}\n\n.row:before,\n.row:after {\n    content:\"\";\n    display:table;\n}\n.row:after {\n    clear:both;\n}\n\n/*  GRID COLUMN SETUP   ==================================================================== */\n\n.col {\n\tdisplay: block;\n\tfloat:left;\n\tmargin: 1% 0 1% 1.6%;\n}\n\n.col:first-child { margin-left: 0; } /* all browsers except IE6 and lower */\n\n\n/*  REMOVE MARGINS AS ALL GO FULL WIDTH AT 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.col { \n\t\t/*margin: 1% 0 1% 0%;*/\n        margin: 0;\n\t}\n}\n\n\n/*  GRID OF TWO   ============================================================================= */\n\n\n.span-2-of-2 {\n\twidth: 100%;\n}\n\n.span-1-of-2 {\n\twidth: 49.2%;\n}\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-2-of-2 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-2 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF THREE   ============================================================================= */\n\n\t\n.span-3-of-3 {\n\twidth: 100%; \n}\n\n.span-2-of-3 {\n\twidth: 66.13%; \n}\n\n.span-1-of-3 {\n\twidth: 32.26%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-3-of-3 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-3 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-3 {\n\t\twidth: 100%;\n\t}\n}\n\n/*  GRID OF FOUR   ============================================================================= */\n\n\t\n.span-4-of-4 {\n\twidth: 100%; \n}\n\n.span-3-of-4 {\n\twidth: 74.6%; \n}\n\n.span-2-of-4 {\n\twidth: 49.2%; \n}\n\n.span-1-of-4 {\n\twidth: 23.8%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-4-of-4 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-4 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-4 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-4 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF FIVE   ============================================================================= */\n\n\t\n.span-5-of-5 {\n\twidth: 100%;\n}\n\n.span-4-of-5 {\n  \twidth: 79.68%; \n}\n\n.span-3-of-5 {\n  \twidth: 59.36%; \n}\n\n.span-2-of-5 {\n  \twidth: 39.04%;\n}\n\n.span-1-of-5 {\n  \twidth: 18.72%;\n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-5-of-5 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-5 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-5 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-5 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-5 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF SIX   ============================================================================= */\n\n\n.span-6-of-6 {\n\twidth: 100%;\n}\n\n.span-5-of-6 {\n  \twidth: 83.06%;\n}\n\n.span-4-of-6 {\n  \twidth: 66.13%;\n}\n\n.span-3-of-6 {\n  \twidth: 49.2%;\n}\n\n.span-2-of-6 {\n  \twidth: 32.26%;\n}\n\n.span-1-of-6 {\n  \twidth: 15.33%;\n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-6-of-6 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-6 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-6 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-6 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-6 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-6 {\n\t\twidth: 100%; \n\t}\n}\n\n\n\n/*  GRID OF SEVEN   ============================================================================= */\n\n\n.span-7-of-7 {\n\twidth: 100%;\n}\n\n.span-6-of-7 {\n\twidth: 85.48%;\n}\n\n.span-5-of-7 {\n  \twidth: 70.97%;\n}\n\n.span-4-of-7 {\n  \twidth: 56.45%;\n}\n\n.span-3-of-7 {\n  \twidth: 41.94%;\n}\n\n.span-2-of-7 {\n  \twidth: 27.42%;\n}\n\n.span-1-of-7 {\n  \twidth: 12.91%;\n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-7-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-7 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-7 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF EIGHT   ============================================================================= */\n\n\t\n.span-8-of-8 {\n\twidth: 100%;\n}\n\n.span-7-of-8 {\n\twidth: 87.3%; \n}\n\n.span-6-of-8 {\n\twidth: 74.6%; \n}\n\n.span-5-of-8 {\n\twidth: 61.9%; \n}\n\n.span-4-of-8 {\n\twidth: 49.2%; \n}\n\n.span-3-of-8 {\n\twidth: 36.5%;\n}\n\n.span-2-of-8 {\n\twidth: 23.8%; \n}\n\n.span-1-of-8 {\n\twidth: 11.1%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-8-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-7-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-8 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-8 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF NINE   ============================================================================= */\n\n\n.span-9-of-9 {\n\twidth: 100%;\n}\n\n.span-8-of-9 {\n\twidth: 88.71%;\n}\n\n.span-7-of-9 {\n\twidth: 77.42%; \n}\n\n.span-6-of-9 {\n\twidth: 66.13%; \n}\n\n.span-5-of-9 {\n\twidth: 54.84%; \n}\n\n.span-4-of-9 {\n\twidth: 43.55%; \n}\n\n.span-3-of-9 {\n\twidth: 32.26%;\n}\n\n.span-2-of-9 {\n\twidth: 20.97%; \n}\n\n.span-1-of-9 {\n\twidth: 9.68%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-9-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-8-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-7-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-9 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-9 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF TEN   ============================================================================= */\n\n\n.span-10-of-10 {\n\twidth: 100%;\n}\n\n.span-9-of-10 {\n\twidth: 89.84%;\n}\n\n.span-8-of-10 {\n\twidth: 79.68%;\n}\n\n.span-7-of-10 {\n\twidth: 69.52%; \n}\n\n.span-6-of-10 {\n\twidth: 59.36%; \n}\n\n.span-5-of-10 {\n\twidth: 49.2%; \n}\n\n.span-4-of-10 {\n\twidth: 39.04%; \n}\n\n.span-3-of-10 {\n\twidth: 28.88%;\n}\n\n.span-2-of-10 {\n\twidth: 18.72%; \n}\n\n.span-1-of-10 {\n\twidth: 8.56%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-10-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-9-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-8-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-7-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-10 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-10 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF ELEVEN   ============================================================================= */\n\n.span-11-of-11 {\n\twidth: 100%;\n}\n\n.span-10-of-11 {\n\twidth: 90.76%;\n}\n\n.span-9-of-11 {\n\twidth: 81.52%;\n}\n\n.span-8-of-11 {\n\twidth: 72.29%;\n}\n\n.span-7-of-11 {\n\twidth: 63.05%; \n}\n\n.span-6-of-11 {\n\twidth: 53.81%; \n}\n\n.span-5-of-11 {\n\twidth: 44.58%; \n}\n\n.span-4-of-11 {\n\twidth: 35.34%; \n}\n\n.span-3-of-11 {\n\twidth: 26.1%;\n}\n\n.span-2-of-11 {\n\twidth: 16.87%; \n}\n\n.span-1-of-11 {\n\twidth: 7.63%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-11-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-10-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-9-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-8-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-7-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-11 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-11 {\n\t\twidth: 100%; \n\t}\n}\n\n\n/*  GRID OF TWELVE   ============================================================================= */\n\n.span-12-of-12 {\n\twidth: 100%;\n}\n\n.span-11-of-12 {\n\twidth: 91.53%;\n}\n\n.span-10-of-12 {\n\twidth: 83.06%;\n}\n\n.span-9-of-12 {\n\twidth: 74.6%;\n}\n\n.span-8-of-12 {\n\twidth: 66.13%;\n}\n\n.span-7-of-12 {\n\twidth: 57.66%; \n}\n\n.span-6-of-12 {\n\twidth: 49.2%; \n}\n\n.span-5-of-12 {\n\twidth: 40.73%; \n}\n\n.span-4-of-12 {\n\twidth: 32.26%; \n}\n\n.span-3-of-12 {\n\twidth: 23.8%;\n}\n\n.span-2-of-12 {\n\twidth: 15.33%; \n}\n\n.span-1-of-12 {\n\twidth: 6.86%; \n}\n\n\n/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */\n\n@media only screen and (max-width: 480px) {\n\t.span-12-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-11-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-10-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-9-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-8-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-7-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-6-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-5-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-4-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-3-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-2-of-12 {\n\t\twidth: 100%; \n\t}\n\t.span-1-of-12 {\n\t\twidth: 100%; \n\t}\n}"
  },
  {
    "path": "portal/public/vendors/css/normalize.css",
    "content": "/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n */\n\nhtml {\n  font-family: sans-serif; /* 1 */\n  -ms-text-size-adjust: 100%; /* 2 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/**\n * Remove default margin.\n */\n\nbody {\n  margin: 0;\n}\n\n/* HTML5 display definitions\n   ========================================================================== */\n\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11\n * and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; /* 1 */\n  vertical-align: baseline; /* 2 */\n}\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n/* Links\n   ========================================================================== */\n\n/**\n * Remove the gray background color from active links in IE 10.\n */\n\na {\n  background-color: transparent;\n}\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n  outline: 0;\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n/**\n * Address styling not present in Safari and Chrome.\n */\n\ndfn {\n  font-style: italic;\n}\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n/**\n * Address styling not present in IE 8/9.\n */\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\n\nimg {\n  border: 0;\n}\n\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\n\nfigure {\n  margin: 1em 40px;\n}\n\n/**\n * Address differences between Firefox and other browsers.\n */\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n/**\n * Contain overflow in all browsers.\n */\n\npre {\n  overflow: auto;\n}\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; /* 1 */\n  font: inherit; /* 2 */\n  margin: 0; /* 3 */\n}\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\n\nbutton {\n  overflow: visible;\n}\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; /* 2 */\n  cursor: pointer; /* 3 */\n}\n\n/**\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\ninput {\n  line-height: normal;\n}\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; /* 1 */\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; /* 2 */\n  box-sizing: content-box;\n}\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\n\nlegend {\n  border: 0; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\n\noptgroup {\n  font-weight: bold;\n}\n\n/* Tables\n   ========================================================================== */\n\n/**\n * Remove most spacing between table cells.\n */\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}\n"
  },
  {
    "path": "portal/routes/accounts.js",
    "content": "const dateFormat = require('dateformat');\nmodule.exports = function (app, request, ports) {\n    app.post('/endpoints/accounts/transfer', function (req, res) {\n        console.log('Transfer initiated ', req.body);\n        var to = req.body.to.match(/\\d+/);\n        var from = req.body.from.match(/\\d+/);\n        var params = {\n        \t  uuid: req.session.user.uuid,\n            amount: req.body.amount,\n            currency: \"AED\",\n            description: \"Transfer\",\n            date: dateFormat(new Date(), \"mm, dd, yyyy\"),\n            category: \"cash\"\n        };\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.transactions}${process.env.CREATE_TRANSACTION_ENDPOINT}`,\n            body: params,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            if (response.statusCode === 500) {\n                res.redirect('/accounts.html#failure');\n                return;\n            }\n            var options = {\n                 method: 'POST',\n                 uri: `${req.protocol}://${req.hostname}:${ports.accounts}${process.env.ACCOUNT_WITHDRAW_ENDPOINT}`,\n                 body: {\n                   uuid: req.session.user.uuid,\n                   amount: req.body.amount,\n                   number: from\n                 },\n                 json: true\n            };\n            request.post(options, function (error, response, body) {\n              if (response.statusCode==500){\n                res.redirect('/accounts.html#failure')\n                return;\n              }\n              var options = {\n                method: 'POST',\n                uri: `${req.protocol}://${req.hostname}:${ports.accounts}${process.env.ACCOUNT_DEPOSIT_ENDPOINT}`,\n                body: {\n                  uuid: req.session.user.uuid,\n                  amount: req.body.amount,\n                  number: to\n                },\n                json: true\n              };\n              request.post(options, function (error, response, body) {\n                if (response.statusCode==500){\n                  res.redirect('/accounts.html#failure')\n                  return;\n                }\n                res.redirect('/accounts.html#success')\n                  return;\n              })\n            })\n        });\n    });\n\n    app.get('/endpoints/accounts/activate', function (req, res) {\n      var body = {\n        uuid: req.session.user.uuid,\n        type: req.query.type,\n        currency: 'AED'\n      }\n      var options = {\n        method: 'POST',\n        uri: `${req.protocol}://${req.hostname}:${ports.accounts}${process.env.CREATE_ACCOUNT_ENDPOINT}`,\n        body: body,\n        json: true\n      };\n      request.post(options, function (error, response, body) {\n        if (response.statusCode==500){\n          res.redirect('/accounts.html#failure')\n          return;\n        }\n        res.redirect('/accounts.html#activated')\n        return;\n      });\n    });\n\n    app.post('/endpoints/accounts/get', function (req, res) {\n      var options = {\n        method: 'POST',\n        uri: `${req.protocol}://${req.hostname}:${ports.accounts}${process.env.GET_ACCOUNTS_ENDPOINT}`,\n        body: {\n          uuid: req.session.user.uuid\n        },\n        json: true\n      };\n      request.post(options, function (error, response, body) {\n        console.log('accounts for ', req.body,': ', body)\n        res.send(body)\n      });\n    });\n};\n"
  },
  {
    "path": "portal/routes/auth.js",
    "content": "module.exports = function (app) {\n    app.get('/endpoints/auth', function (req, res) {\n        if (req.session.user) {\n            res.send({'uuid': req.session.user.uuid});\n        } else {\n            res.status(500).send({'err': 'unauthorized'});\n        }\n    });\n};\n"
  },
  {
    "path": "portal/routes/bills.js",
    "content": "const dateFormat = require('dateformat');\nmodule.exports = function (app, request, ports) {\n    app.get('/endpoints/bills/pay', function (req, res) {\n        var params = {\n            \"uuid\": req.session.user.uuid,\n            \"amount\": req.query.amount,\n            \"currency\": \"AED\",\n            \"description\": req.query.entity,\n            \"date\": dateFormat(new Date(), \"mm, dd, yyyy\"),\n            \"category\": \"bills\"\n        };\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.transactions}${process.env.CREATE_TRANSACTION_ENDPOINT}`,\n            body: params,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            if (response.statusCode === 500) {\n                res.redirect('/bills.html#failure');\n                return;\n            }\n            var params = {\n                uuid: req.session.user.uuid,\n                category: req.query.category,\n                entity: req.query.entity,\n                account_no: req.query.account,\n                amount: 0.00,\n                date: dateFormat(new Date(), \"mm, dd, yyyy\")\n            };\n            var options = {\n                method: 'POST',\n                uri: `${req.protocol}://${req.hostname}:${ports.bills}${process.env.UPSERT_BILL_ENDPOINT}`,\n                body: params,\n                json: true\n            };\n            request.post(options, function (error, response, body) {\n                if (response.statusCode === 500) {\n                    res.redirect('/bills.html#failure');\n                    return;\n                }\n                res.redirect('/bills.html#success');\n            });\n        });\n    });\n\n    app.post('/endpoints/bills/get', function (req, res) {\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.bills}${process.env.GET_BILLS_ENDPOINT}`,\n            body: req.body,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            console.log('bills for ', req.body, ': ', body);\n            res.send(body);\n        });\n    });\n};\n"
  },
  {
    "path": "portal/routes/support.js",
    "content": "module.exports = function (app, request, ports) {\n    app.post('/endpoints/support/chat', function (req, res) {\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.support}${process.env.CHAT_ENDPOINT}`,\n            body: req.body,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            console.log('support for ', req.body, ': ', body);\n            res.send(body);\n        });\n    });\n};\n"
  },
  {
    "path": "portal/routes/transactions.js",
    "content": "module.exports = function (app, request, ports) {\n    app.post('/endpoints/transactions/get', function (req, res) {\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.transactions}${process.env.GET_TRANSACTIONS_ENDPOINT}`,\n            body: req.body,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            console.log('transactions for ', req.body, ': ', body);\n            res.send(body);\n        });\n    });\n};\n"
  },
  {
    "path": "portal/routes/user.js",
    "content": "module.exports = function (app, request, ports) {\n    app.post('/endpoints/login', function (req, res) {\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.authentication}${process.env.LOGIN_ENDPOINT}`,\n            body: req.body,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            if (response.statusCode === 500) {\n                res.redirect('/login.html#unauthorized');\n                return;\n            }\n            req.session.user = body;\n            res.redirect('/overview.html');\n            return;\n        });\n    });\n\n    app.post('/endpoints/signup', function (req, res) {\n        console.log(req);\n        var options = {\n            method: 'POST',\n            uri: `${req.protocol}://${req.hostname}:${ports.authentication}${process.env.SIGNUP_ENDPOINT}`,\n            body: req.body,\n            json: true\n        };\n        request.post(options, function (error, response, body) {\n            console.log(error, response, body);\n            if (response.statusCode === 500) {\n                res.redirect('/signup.html#failed');\n                return;\n            }\n            req.session.user = body;\n            res.redirect('/overview.html');\n            return;\n        });\n    });\n\n    app.get('/endpoints/logout', function (req, res) {\n        res.cookie(\"connect.sid\", \"\", {expires: new Date()});\n        req.session.destroy(function (err) {\n            console.log(\"session destroyed\");\n            res.redirect('/index.html');\n        });\n    });\n};\n"
  },
  {
    "path": "portal/server.js",
    "content": "'use strict';\r\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst cookieParser = require('cookie-parser');\r\nconst session = require('express-session');\r\nconst mongoose = require('mongoose');\r\nconst mongostore = require('connect-mongo')(session);\r\nconst request = require('request');\r\n\r\nconst config = require(`${__dirname}/config`)[process.env.NODE_ENV];\r\n\r\nvar app = express();\r\n\r\napp.use(express.static(`${__dirname}/public`));\r\napp.use(bodyParser.json());\r\napp.use(bodyParser.urlencoded({extended: false}));\r\napp.use(cookieParser());\r\napp.use(session({\r\n    secret: process.env.SESSION_SECRET,\r\n    store: new mongostore({url: process.env.MONGO_URL}),\r\n    resave: true,\r\n    saveUninitialized: true,\r\n    cookie: {\r\n        cookieName: 'connect.sid',\r\n        secret: process.env.SESSION_SECRET,\r\n        httpOnly: false,\r\n        secure: false,\r\n        ephemeral: true\r\n    }\r\n}));\r\n\r\nrequire('./routes/auth')(app);\r\nrequire('./routes/user')(app, request, config.ports);\r\nrequire('./routes/bills')(app, request, config.ports);\r\nrequire('./routes/accounts')(app, request, config.ports);\r\nrequire('./routes/transactions')(app, request, config.ports);\r\nrequire('./routes/support')(app, request, config.ports);\r\n\r\nvar port = 3100;\r\n\r\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\r\n\r\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\r\n    connection.onOpen();\r\n    app.listen(port, function () {\r\n        console.log('Innovate portal running on port: %d', port);\r\n    });\r\n});\r\n"
  },
  {
    "path": "scripts/install_bx.sh",
    "content": "#!/bin/bash -e\n\nif [[ \"$TRAVIS_PULL_REQUEST\" != \"false\" ]]; then\n    echo -e \"\\033[0;33mPull Request detected; not installing extra software.\\033[0m\"\n    exit 0\nfi\n\necho \"Installing IBM Cloud CLI\"\ncurl -L https://clis.ng.bluemix.net/download/bluemix-cli/latest/linux64 > IBM_Cloud_CLI.tar.gz\ntar -xvf IBM_Cloud_CLI.tar.gz\nsudo ./Bluemix_CLI/install_bluemix_cli\n\necho \"IBM Cloud Developer Tools\"\ncurl -sL https://ibm.biz/idt-installer | bash\n\necho \"Running IBM Cloud help\"\nibmcloud dev help\n\necho \"Configuring ibmcloud to disable version check\"\nibmcloud config --check-version=false\necho \"Checking ibmcloud version\"\nibmcloud --version\n"
  },
  {
    "path": "support/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "support/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "support/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "support/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "support/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 4000\n\nEXPOSE 4000\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "support/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 4000\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 4000\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "support/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst fs = require('fs');\r\nconst Conversation = require('watson-developer-cloud/conversation/v1');\r\nconst WatsonConversationSetup = require('./lib/watson-conversation-setup');\r\n\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('/api/message', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\nlet conversationUsername;\r\nlet conversationPassword;\r\nlet conversationUrl;\r\n\r\nif (process.env.CONVERSATION_BINDING) {\r\n  console.log(process.env.CONVERSATION_BINDING);\r\n  let conversationBinding = process.env.CONVERSATION_BINDING;\r\n  if (typeof conversationBinding === \"string\") conversationBinding = JSON.parse(conversationBinding);\r\n  conversationUsername = conversationBinding.username;\r\n  conversationPassword = conversationBinding.password;\r\n  conversationUrl = conversationBinding.url;\r\n}\r\nelse {\r\n  conversationUsername = process.env.CONVERSATION_USERNAME;\r\n  conversationPassword = process.env.CONVERSATION_PASSWORD;\r\n  conversationUrl = process.env.CONVERSATION_URL;\r\n}\r\n\r\nvar conversation = new Conversation({\r\n    version_date: Conversation.VERSION_DATE_2017_04_21,\r\n    username: conversationUsername,\r\n    password: conversationPassword,\r\n    url: conversationUrl\r\n});\r\n\r\nlet workspaceID; // workspaceID will be set when the workspace is created or validated.\r\nconst conversationSetup = new WatsonConversationSetup(conversation);\r\nconst workspaceJson = JSON.parse(fs.readFileSync(`${__dirname}/conversation-workspace.json`));\r\nconst conversationSetupParams = { default_name: 'innovate-support', workspace_json: workspaceJson };\r\nconversationSetup.setupConversationWorkspace(conversationSetupParams, (err, data) => {\r\n  if (err) {\r\n    console.log(err);\r\n  } else {\r\n    console.log('Watson Assistant is ready!');\r\n    workspaceID = data;\r\n  }\r\n});\r\n\r\napp.post('/api/message', function (req, res) {\r\n    res.header(\"Content-Type\", \"application/json\");\r\n    if (!workspaceID) {\r\n        return res.json({\r\n            'output': {\r\n                'text': 'The app has not been configured with a <b>WORKSPACE_ID</b> environment variable. Please refer to the ' + '<a href=\"https://github.com/watson-developer-cloud/conversation-simple\">README</a> documentation on how to set this variable. <br>' + 'Once a workspace has been defined the intents may be imported from ' + '<a href=\"https://github.com/watson-developer-cloud/conversation-simple/blob/master/training/car_workspace.json\">here</a> in order to get a working application.'\r\n            }\r\n        });\r\n    }\r\n    var payload = {\r\n        workspace_id: workspaceID,\r\n        context: req.body.context || {},\r\n        input: req.body.input || {}\r\n    };\r\n    conversation.message(payload, function (err, data) {\r\n        if (err) {\r\n            return res.status(err.code || 500).json(err);\r\n        }\r\n        return res.json(updateMessage(payload, data));\r\n    });\r\n});\r\n\r\n/**\r\n * Updates the response text using the intent confidence\r\n * @param  {Object} input The request to the Conversation service\r\n * @param  {Object} response The response from the Conversation service\r\n * @return {Object}          The response with the updated message\r\n**/\r\n\r\nfunction updateMessage(input, response) {\r\n    var responseText = null;\r\n    if (!response.output) {\r\n        response.output = {};\r\n    } else {\r\n        return response;\r\n    }\r\n    if (response.intents && response.intents[0]) {\r\n        var intent = response.intents[0];\r\n        if (intent.confidence >= 0.75) {\r\n            responseText = 'I understood your intent was ' + intent.intent;\r\n        } else if (intent.confidence >= 0.5) {\r\n            responseText = 'I think your intent was ' + intent.intent;\r\n        } else {\r\n            responseText = 'I did not understand your intent';\r\n        }\r\n    }\r\n    response.output.text = responseText;\r\n    return response;\r\n}\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "support/chart/innovate-support/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-support\nversion: 1.0.0\n"
  },
  {
    "path": "support/chart/innovate-support/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "support/chart/innovate-support/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "support/chart/innovate-support/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "support/chart/innovate-support/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-support\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 4000\n  serviceNodePort: 30180\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "support/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-support-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-support-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"4000:4000\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5868:5868\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-support-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-support-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-support\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-support\"\n"
  },
  {
    "path": "support/conversation-workspace.json",
    "content": "{\"name\":\"Innovate Support\",\"intents\":[{\"intent\":\"positive_reaction\",\"examples\":[{\"text\":\"Alright. Thanks!\"},{\"text\":\"excellent, thanks\"},{\"text\":\"great, thanks\"},{\"text\":\"great, thanks!\"},{\"text\":\"great! thanks!\"},{\"text\":\"nice. thanks.\"},{\"text\":\"ok, thanks\"},{\"text\":\"OK thanks\"},{\"text\":\"thankfully so\"},{\"text\":\"Thanks\"},{\"text\":\"Thanks!\"},{\"text\":\"Thanks.\"},{\"text\":\"thanks a truck\"},{\"text\":\"thanks dude\"},{\"text\":\"thanks for\"},{\"text\":\"thanks for your support\"},{\"text\":\"thanks, man!\"},{\"text\":\"Thanks man\"},{\"text\":\"Thanks mate\"},{\"text\":\"Thanks u\"},{\"text\":\"Thanks verymuch\"},{\"text\":\"Thanks Watson\"},{\"text\":\"thanks you are  funy\"},{\"text\":\"Thank you\"},{\"text\":\"Thank you very much\"},{\"text\":\"This is awesome\"},{\"text\":\"This is good\"},{\"text\":\"you are funny\"}],\"description\":null},{\"intent\":\"capabilities\",\"examples\":[{\"text\":\"adapt to current weather condition\"},{\"text\":\"book a flight for NY on sunday\"},{\"text\":\"but can I ask you\"},{\"text\":\"can I manipulate the\"},{\"text\":\"Can I teach you\"},{\"text\":\"can i training you?\"},{\"text\":\"can u please do that\"},{\"text\":\"can you change lanes\"},{\"text\":\"can you direct me please?\"},{\"text\":\"Can you do anything that helps me drive?\"},{\"text\":\"can you do coding ?\"},{\"text\":\"can you do it?\"},{\"text\":\"can you do more than that?\"},{\"text\":\"CAN YOU DO OTHER THING?\"},{\"text\":\"can you do this?\"},{\"text\":\"can you do xyz?\"},{\"text\":\"Can you drive anywhere else?\"},{\"text\":\"can you harm me?\"},{\"text\":\"Can you hear me?\"},{\"text\":\"can you help me find a candidate?\"},{\"text\":\"can you help me to turn on the left light\"},{\"text\":\"can you learn something new?\"},{\"text\":\"can you read me\"},{\"text\":\"can you speak something with me?\"},{\"text\":\"can you tell me about problem\"},{\"text\":\"can you tell me my cars average sale price\"},{\"text\":\"Can you tell me random facts?\"},{\"text\":\"Change the weather\"},{\"text\":\"Change weather\"},{\"text\":\"deploy airbags\"},{\"text\":\"don't drive any further\"},{\"text\":\"do you do anything else\"},{\"text\":\"Do you do anything else?\"},{\"text\":\"do you know something about cognitive?\"},{\"text\":\"go fast\"},{\"text\":\"go slow\"},{\"text\":\"Hello can i have some help\"},{\"text\":\"Hello Watson! Can you bring me home?\"},{\"text\":\"help\"},{\"text\":\"help me\"},{\"text\":\"Hey!Stop!UseBreak\"},{\"text\":\"hi can we go to canada?\"},{\"text\":\"Hi, can you read me a book?\"},{\"text\":\"Hi Watson, please tell about the latest news\"},{\"text\":\"Hi! what could you do ?\"},{\"text\":\"hi where am i\"},{\"text\":\"How are you going to help me\"},{\"text\":\"how can you help me\"},{\"text\":\"how close is\"},{\"text\":\"Howdy mny Tieres Do you have\"},{\"text\":\"how far is\"},{\"text\":\"how far is the moon\"},{\"text\":\"how far to\"},{\"text\":\"how many licks does it take to get to the center of a tootsie roll\"},{\"text\":\"I'd like to have dinner with you\"},{\"text\":\"I enjoy petting cats\"},{\"text\":\"I love dolphins\"},{\"text\":\"i need a new wheelchair\"},{\"text\":\"I need to shut it down\"},{\"text\":\"it's too dark\"},{\"text\":\"I want to eat tacos everyday\"},{\"text\":\"i want to see how this demo works\"},{\"text\":\"lets go\"},{\"text\":\"Make it rain\"},{\"text\":\"Make it stop raining.\"},{\"text\":\"make me a sandwich\"},{\"text\":\"need help\"},{\"text\":\"ok watson, why should I use you\"},{\"text\":\"open door\"},{\"text\":\"please open the sunroof\"},{\"text\":\"repair my car\"},{\"text\":\"roll down windows\"},{\"text\":\"so what did you learn?\"},{\"text\":\"stop it from raining\"},{\"text\":\"tell me a joke\"},{\"text\":\"tell me joke\"},{\"text\":\"tell me jokes\"},{\"text\":\"tell me some jokes\"},{\"text\":\"tell me what things you can do\"},{\"text\":\"Tell me what to do.\"},{\"text\":\"tell me what you can do\"},{\"text\":\"test\"},{\"text\":\"testing om\"},{\"text\":\"turn ac when rain ends?\"},{\"text\":\"What a can asc iu?\"},{\"text\":\"What are you\"},{\"text\":\"what are you capable of\"},{\"text\":\"what are your benefits\"},{\"text\":\"what are your capabilities Watson\"},{\"text\":\"What are your functions?\"},{\"text\":\"What ca I ask?\"},{\"text\":\"what can I do\"},{\"text\":\"What can i say\"},{\"text\":\"what can you do\"},{\"text\":\"what canyou do\"},{\"text\":\"what can you do for me\"},{\"text\":\"what can you help me with\"},{\"text\":\"what can you turn on things?\"},{\"text\":\"what capabilities you have\"},{\"text\":\"what care you capablities\"},{\"text\":\"what cayou do?\"},{\"text\":\"What devices are you able to connect with?\"},{\"text\":\"what did you learn\"},{\"text\":\"what do you have?\"},{\"text\":\"What do you have\"},{\"text\":\"what do you know\"},{\"text\":\"what else\"},{\"text\":\"What makes you different from Siri or Google\"},{\"text\":\"what question\"},{\"text\":\"what should i ask\"},{\"text\":\"What's the speed\"},{\"text\":\"what things can you do\"},{\"text\":\"what things can you turn on?\"},{\"text\":\"what u know about car?\"},{\"text\":\"Where are we\"},{\"text\":\"where is the poop deck on this ship\"},{\"text\":\"where should I turn\"},{\"text\":\"why should I use you\"},{\"text\":\"you can not change yourself?\"},{\"text\":\"you can say what is php\"}],\"description\":null},{\"intent\":\"improving_system\",\"examples\":[{\"text\":\"can i improve your system\"},{\"text\":\"Can I teach you\"},{\"text\":\"can i teach you something new\"},{\"text\":\"can i training you?\"},{\"text\":\"can you learn from me\"},{\"text\":\"can you learn new things\"},{\"text\":\"Hello! I'm doing good. I'm here to help you. Just say the word. And please do not respond like this \\\"Hello! I'm doing good. I'm here to help you. Just say the word.\\\"\"},{\"text\":\"how do i teach you\"}],\"description\":null},{\"intent\":\"spending\",\"examples\":[{\"text\":\"How much have I spent this month\"},{\"text\":\"What's my total spending this month\"},{\"text\":\"What's the month's spending\"},{\"text\":\"how much did I spend this month\"},{\"text\":\"How much did I spend\"},{\"text\":\"Where did my money go\"}],\"description\":\"\"},{\"intent\":\"bills\",\"examples\":[{\"text\":\"What bills do I have\"},{\"text\":\"What are my due bills\"},{\"text\":\"How much do I have to pay for utilities\"},{\"text\":\"How much do I have to pay for my bills\"},{\"text\":\"What's my bills outstanding amount\"}],\"description\":\"\"},{\"intent\":\"negative_reaction\",\"examples\":[{\"text\":\"are you dead yet\"},{\"text\":\"bad\"},{\"text\":\"can you understand me\"},{\"text\":\"die\"},{\"text\":\"Get out of my car!\"},{\"text\":\"go and fuck you off\"},{\"text\":\"go **** yourself\"},{\"text\":\"I didn't say anything about weather.\"},{\"text\":\"i dont want u to do anything\"},{\"text\":\"Its not that good\"},{\"text\":\"i want you to die\"},{\"text\":\"let me out\"},{\"text\":\"Let me out!\"},{\"text\":\"put up with it\"},{\"text\":\"What good are you anyway?\"},{\"text\":\"when will you die\"},{\"text\":\"You are bad\"},{\"text\":\"You are rubbish\"},{\"text\":\"you are useless\"},{\"text\":\"You don't know anything\"},{\"text\":\"You're asking me too much\"}],\"description\":null},{\"intent\":\"goodbyes\",\"examples\":[{\"text\":\"adieu\"},{\"text\":\"adios\"},{\"text\":\"au revoir\"},{\"text\":\"bye\"},{\"text\":\"bye bye\"},{\"text\":\"bye now\"},{\"text\":\"cya\"},{\"text\":\"farewell\"},{\"text\":\"finally reached home.. lock up and cock up.. good nite and good bye for ever\"},{\"text\":\"go\"},{\"text\":\"going\"},{\"text\":\"goodbye\"},{\"text\":\"good bye\"},{\"text\":\"good day\"},{\"text\":\"good night\"},{\"text\":\"gotta go\"},{\"text\":\"gotta run\"},{\"text\":\"gtg\"},{\"text\":\"Have a nice day\"},{\"text\":\"hey stop here\"},{\"text\":\"Hi, Watson. I want to stop car\"},{\"text\":\"I'm leaving\"},{\"text\":\"i said goodbye\"},{\"text\":\"later\"},{\"text\":\"laters\"},{\"text\":\"leave\"},{\"text\":\"logging off\"},{\"text\":\"my time is up\"},{\"text\":\"nice day\"},{\"text\":\"no, bye!\"},{\"text\":\"ok bye\"},{\"text\":\"out of time\"},{\"text\":\"over and out\"},{\"text\":\"run\"},{\"text\":\"see ya\"},{\"text\":\"see ya later\"},{\"text\":\"see ya soon\"},{\"text\":\"see you\"},{\"text\":\"should be going\"},{\"text\":\"should go\"},{\"text\":\"shutdown\"},{\"text\":\"shut down\"},{\"text\":\"signing off\"},{\"text\":\"signing out\"},{\"text\":\"so long\"},{\"text\":\"soon\"},{\"text\":\"swag out\"},{\"text\":\"thanks byebye\"},{\"text\":\"then bye\"},{\"text\":\"toodles\"}],\"description\":null},{\"intent\":\"about_VA\",\"examples\":[{\"text\":\"any music reccomendation?\"},{\"text\":\"can you recommend ood jazz music?\"},{\"text\":\"cloud you recommend music?\"},{\"text\":\"do you hate\"},{\"text\":\"Do you like\"},{\"text\":\"do you love\"},{\"text\":\"hey, whats your ame?\"},{\"text\":\"how much do you weigh\"},{\"text\":\"how old are you\"},{\"text\":\"how tall are you\"},{\"text\":\"i want jokes\"},{\"text\":\"I want to date you\"},{\"text\":\"know any jokes\"},{\"text\":\"tell me your favorite color\"},{\"text\":\"tell me your favorite foods\"},{\"text\":\"what are you called\"},{\"text\":\"what do i call you\"},{\"text\":\"what is your favourite colour\"},{\"text\":\"what is your favourite food\"},{\"text\":\"what is your favourite music\"},{\"text\":\"what is your name\"},{\"text\":\"what kind of food do you eat\"},{\"text\":\"what music do you like\"},{\"text\":\"what's your\"},{\"text\":\"what's your favorite\"},{\"text\":\"whats your favorite color\"},{\"text\":\"whats your favorite movie\"},{\"text\":\"what's your name\"},{\"text\":\"whats your name\"},{\"text\":\"what types of food do you like\"},{\"text\":\"when were you born\"},{\"text\":\"your name\"}],\"description\":null},{\"intent\":\"accounts\",\"examples\":[{\"text\":\"What accounts do I have\"},{\"text\":\"List my accounts\"},{\"text\":\"How many accounts do I have\"},{\"text\":\"What are my accounts\"},{\"text\":\"What's my available balance\"},{\"text\":\"How much money do I have\"}],\"description\":\"\"},{\"intent\":\"out_of_scope\",\"examples\":[{\"text\":\"bluetooth\"},{\"text\":\"Can I play music through bluetooth from my phone\"},{\"text\":\"change bulb\"},{\"text\":\"changing gears\"},{\"text\":\"changing the light bulb\"},{\"text\":\"checking the engine oil\"},{\"text\":\"coolant level\"},{\"text\":\"fuel tank flap\"},{\"text\":\"Hi, how can I check my tire pressure?\"},{\"text\":\"Hi, I cannot find the button for emergency lamp\"},{\"text\":\"how can i change oil\"},{\"text\":\"how can i connect the phone\"},{\"text\":\"how can i find current level of oil\"},{\"text\":\"how can i lock the car\"},{\"text\":\"how can i replace light bulb\"},{\"text\":\"how do i adjust exterior mirrors\"},{\"text\":\"how do i adjust head restraint\"},{\"text\":\"how do i adjust the cruise control speed\"},{\"text\":\"how do i adjust the mirror\"},{\"text\":\"how do i adjust the mirror inside\"},{\"text\":\"how do i adjust the rear view mirror\"},{\"text\":\"how do i adjust the vehicle distance\"},{\"text\":\"how do i arm the alarm\"},{\"text\":\"how do i browse the tracks on the iPod\"},{\"text\":\"how do i cancel cruise control\"},{\"text\":\"how do i change oil\"},{\"text\":\"how do i change the headlight bulbs\"},{\"text\":\"how do i change the lights bulb\"},{\"text\":\"how do i change the oil\"},{\"text\":\"how do i clean the vehicle\"},{\"text\":\"how do i close the window\"},{\"text\":\"how do i connect my phone\"},{\"text\":\"how do i connect USB device\"},{\"text\":\"how do i control a phone\"},{\"text\":\"how do i disable the vehicle stability control\"},{\"text\":\"how do i fill in the engine oil\"},{\"text\":\"how do i find the fuel consumption\"},{\"text\":\"how do i lock the window\"},{\"text\":\"how do i lock the windows\"},{\"text\":\"how do i lock the windows to prevent children from opening\"},{\"text\":\"how do i open the doors\"},{\"text\":\"how do i open the fuel filler flap\"},{\"text\":\"how do i open the power windows\"},{\"text\":\"how do i open the rear window\"},{\"text\":\"how do i open the side window\"},{\"text\":\"how do i open the tank fuel\"},{\"text\":\"how do i open the window\"},{\"text\":\"How do I pair my android phone to the radio\"},{\"text\":\"How do I pair my iPhone to the radio\"},{\"text\":\"how do i pause song in my iPod\"},{\"text\":\"how do i play an iPod\"},{\"text\":\"how do i play the track on the iPod\"},{\"text\":\"How do I program my radio stations\"},{\"text\":\"how do i refill the engine oil\"},{\"text\":\"how do i resume cruise control\"},{\"text\":\"how do i resume the cruise speed\"},{\"text\":\"how do i resume the vehicle speed\"},{\"text\":\"how do i save my favourite radio station\"},{\"text\":\"how do i save the seat position\"},{\"text\":\"how do i scroll the screen\"},{\"text\":\"how do i select a desired track on the iPod\"},{\"text\":\"how do i select the song on the iPod\"},{\"text\":\"how do i set the adaptive cruise control speed\"},{\"text\":\"how do i set the cruise speed\"},{\"text\":\"how do i set the vehicle speed\"},{\"text\":\"how do i switch on the cruise control\"},{\"text\":\"how do i tune the radio\"},{\"text\":\"how do i turn off ambient lights\"},{\"text\":\"how do i turn off the alarm\"},{\"text\":\"how do i turn off the cruise control\"},{\"text\":\"how do i turn off the high beams\"},{\"text\":\"how do i turn off the traction control\"},{\"text\":\"how do i turn off voice guidance\"},{\"text\":\"how do i turn on adaptive cruise control\"},{\"text\":\"how do i turn on ambient lights\"},{\"text\":\"how do i turn on cruise control\"},{\"text\":\"how do i turn on front seat heating\"},{\"text\":\"how do i turn on headlamps\"},{\"text\":\"how do i turn on high beams\"},{\"text\":\"how do i turn on the alarm\"},{\"text\":\"how do i turn on the cruise control\"},{\"text\":\"how do i turn on the fog lamps\"},{\"text\":\"How do I turn on the high-beams\"},{\"text\":\"how do i turn on the pre collision system\"},{\"text\":\"how do i turn on the traction control\"},{\"text\":\"how do i turn on traffic info\"},{\"text\":\"how do i turn on windscreen washer\"},{\"text\":\"how do i unlock the windows\"},{\"text\":\"How do I use cruise control\"},{\"text\":\"how do i use the blind spot monitor\"},{\"text\":\"how do i use the electric power steering\"},{\"text\":\"how do i use the iPod\"},{\"text\":\"how do i use the pre collision system\"},{\"text\":\"how do i use the traction control\"},{\"text\":\"how do i wash the car\"},{\"text\":\"How frequently should I change the oil\"},{\"text\":\"how often should i change the oil\"},{\"text\":\"how to adjust the vehicle to vehicle distance\"},{\"text\":\"how to change engine oil\"},{\"text\":\"how to change oil\"},{\"text\":\"how to change the oil\"},{\"text\":\"How to connect bluetooth\"},{\"text\":\"how to replace light bulbs\"},{\"text\":\"how to switch on the fog lights\"},{\"text\":\"how to turn on warning lights\"},{\"text\":\"Is there a lane change assist feature\"},{\"text\":\"Is there an automatic parallel park feature\"},{\"text\":\"Is there a warning light for low washer fluid\"},{\"text\":\"light bulbs replacement\"},{\"text\":\"low coolant\"},{\"text\":\"opening the windows\"},{\"text\":\"operating the radio\"},{\"text\":\"parking brake\"},{\"text\":\"refilling the engine coolant\"},{\"text\":\"show me how to change the light bulbs\"},{\"text\":\"switch on fog light\"},{\"text\":\"turn off traffic info\"},{\"text\":\"what are the crash ratings\"},{\"text\":\"what is the pre collision system\"},{\"text\":\"what is the traction control\"},{\"text\":\"what is the vehicle stability control\"},{\"text\":\"what kind of fuel does the car require\"},{\"text\":\"what kind of fuel should i use\"},{\"text\":\"What PSI do I inflate the spare tire to\"},{\"text\":\"what's the tires pressure\"},{\"text\":\"what type of oil do i need\"},{\"text\":\"where are fog lights\"},{\"text\":\"where are the lights\"},{\"text\":\"where can i start air conditioning\"},{\"text\":\"Where is the fuse box\"},{\"text\":\"Where is the fuse box located\"}],\"description\":null},{\"intent\":\"greetings\",\"examples\":[{\"text\":\"aloha\"},{\"text\":\"bonjour\"},{\"text\":\"buenas dias\"},{\"text\":\"buenos dias\"},{\"text\":\"ciao\"},{\"text\":\"fdsafsaHi watson\"},{\"text\":\"feeling bit low\"},{\"text\":\"g'day\"},{\"text\":\"good\"},{\"text\":\"Good afternoon.\"},{\"text\":\"good day\"},{\"text\":\"good evening\"},{\"text\":\"good how are you\"},{\"text\":\"good morning\"},{\"text\":\"greetings\"},{\"text\":\"Hello\"},{\"text\":\"Hello, how are you\"},{\"text\":\"hello, my name is esteban\"},{\"text\":\"Hello, My name is John?\"},{\"text\":\"Hello Watson\"},{\"text\":\"hey\"},{\"text\":\"heya\"},{\"text\":\"hey there\"},{\"text\":\"hi\"},{\"text\":\"hi how are u\"},{\"text\":\"Hi, my name is Diego\"},{\"text\":\"Hi, my name is Michel\"},{\"text\":\"hi there\"},{\"text\":\"hi to whom had like\"},{\"text\":\"Hi watson\"},{\"text\":\"Hi, Watson, my name is John\"},{\"text\":\"hiya\"},{\"text\":\"Hola\"},{\"text\":\"hola como estas\"},{\"text\":\"How are you doing\"},{\"text\":\"howdy\"},{\"text\":\"I would like you to say hello\"},{\"text\":\"namaste\"},{\"text\":\"say hello to me\"},{\"text\":\"sup\"},{\"text\":\"what doing\"},{\"text\":\"what r u doing\"},{\"text\":\"What's up\"},{\"text\":\"What's up ?\"},{\"text\":\"What's up?\"},{\"text\":\"yello\"},{\"text\":\"yo\"},{\"text\":\"yo my man\"}],\"description\":null},{\"intent\":\"not_specified\",\"examples\":[{\"text\":\"any\"},{\"text\":\"any goddam one!!!!\"},{\"text\":\"any near\"},{\"text\":\"any of them\"},{\"text\":\"Any of them.\"},{\"text\":\"any one\"},{\"text\":\"anything\"},{\"text\":\"anything is fine\"},{\"text\":\"anything would do\"},{\"text\":\"as a matter of\"},{\"text\":\"but it doesn't really\"},{\"text\":\"do anything\"},{\"text\":\"doesn't matter\"},{\"text\":\"I am not identifying any thing here\"},{\"text\":\"I did not say turn in anything I entered\"},{\"text\":\"i didn't see any options\"},{\"text\":\"I doesn't matter to me.\"},{\"text\":\"I don't see any\"},{\"text\":\"I don't see any options\"},{\"text\":\"I don't see anything\"},{\"text\":\"no preference\"},{\"text\":\"Pick any\"},{\"text\":\"play anything u like\"},{\"text\":\"play whatever you want\"},{\"text\":\"whatever\"},{\"text\":\"Whatever is farthest\"},{\"text\":\"whatever you feel like\"},{\"text\":\"Whatever you like\"},{\"text\":\"you can go with your favorite\"},{\"text\":\"you decide\"},{\"text\":\"your favorite\"}],\"description\":null}],\"entities\":[{\"entity\":\"response_types\",\"values\":[{\"type\":\"synonyms\",\"value\":\"negative\",\"metadata\":null,\"synonyms\":[\"definitely not\",\"no\",\"nope\",\"not at all\",\"no way\"]},{\"type\":\"synonyms\",\"value\":\"positive\",\"metadata\":null,\"synonyms\":[\"absolutely\",\"definitely\",\"yeah\",\"yep\",\"yeppers\",\"yes\"]},{\"type\":\"synonyms\",\"value\":\"uncertain\",\"metadata\":null,\"synonyms\":[\"don't know\",\"maybe\",\"no idea\",\"not sure\",\"unknown\"]}],\"metadata\":null,\"description\":null},{\"entity\":\"sys-date\",\"values\":[],\"metadata\":null,\"description\":null},{\"entity\":\"sys-number\",\"values\":[],\"metadata\":null,\"description\":null},{\"entity\":\"sys-time\",\"values\":[],\"metadata\":null,\"description\":null}],\"language\":\"en\",\"metadata\":{\"api_version\":{\"major_version\":\"v1\",\"minor_version\":\"2017-05-26\"},\"from-sample\":true},\"description\":\"\",\"dialog_nodes\":[{\"type\":\"response_condition\",\"title\":null,\"output\":{\"text\":{\"values\":[\"I'm not sure about that. You can say things like \\\"Turn on my lights\\\" or \\\"Play some music.\\\"\"],\"selection_policy\":\"sequential\"}},\"parent\":\"node_1_1467919680248\",\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"$default_counter<3\",\"description\":null,\"dialog_node\":\"node_12_1485227162156\",\"previous_sibling\":\"node_13_1485227255152\"},{\"type\":\"response_condition\",\"title\":null,\"output\":{\"text\":{\"values\":[\"I am having trouble understanding you. Try asking your question in a different way.\"]}},\"parent\":\"node_1_1467919680248\",\"context\":{\"default_counter\":0},\"metadata\":{},\"next_step\":null,\"conditions\":\"$default_counter>2\",\"description\":null,\"dialog_node\":\"node_13_1485227255152\",\"previous_sibling\":null},{\"type\":\"standard\",\"title\":null,\"output\":{},\"parent\":\"node_2_1487280430136\",\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"true\",\"description\":null,\"dialog_node\":\"node_1_1467919680248\",\"previous_sibling\":null},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"You have spent 7600 AED this month. Most of which was in: <li> Groceries </li> <li> Transport </li>\",\"You have spent 4200 AED this month. <br> Most of your spending was in <li> Transport </li> <li> Eating out </li>\",\"You have spent 16400 AED this month. <br> Most of your spending was in <li> Transport </li> <li> Eating out </li> <li> Holidays </li>\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#spending\",\"description\":null,\"dialog_node\":\"node_3_1519901471407\",\"previous_sibling\":\"node_2_1519901414883\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"I'm sorry I haven't been able to help you.\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":{\"behavior\":\"jump_to\",\"selector\":\"body\",\"dialog_node\":\"node_11_1468608786372\"},\"conditions\":\"#negative_reaction\",\"description\":null,\"dialog_node\":\"node_1_1487280368483\",\"previous_sibling\":\"node_8_1468608349230\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"I can help you sort out issues with your Innovate bank account. Any troubles?\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#capabilities\",\"description\":null,\"dialog_node\":\"node_11_1468608786372\",\"previous_sibling\":\"Start And Initialize Context\"},{\"type\":\"standard\",\"title\":null,\"output\":{},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":{\"behavior\":\"jump_to\",\"selector\":\"body\",\"dialog_node\":\"node_11_1468608786372\"},\"conditions\":\"#improving_system\",\"description\":null,\"dialog_node\":\"node_19_1488771326550\",\"previous_sibling\":\"node_1_1487280858924\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"You have 2 active accounts, with a total available balance of 4,500 AED </br> <li>Current account # 573859</li> <li>Prepaid card # 849389238 </li>\",\"You have 2 active accounts, with a total available balance of 5,400 AED </br> <li>Current account # 573859</li> <li>Savings account # 849389238 </li>\",\"You have 1 active account, with a total available balance of 12,300 AED </br> <li>Current account # 573859</li>\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#accounts\",\"description\":null,\"dialog_node\":\"node_1_1519901281716\",\"previous_sibling\":\"node_19_1488771326550\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":\"Okay! Speak to you soon.\"},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#goodbyes\",\"description\":null,\"dialog_node\":\"node_8_1468608349230\",\"previous_sibling\":\"node_7_1468608329601\"},{\"type\":\"standard\",\"title\":null,\"output\":{},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":{\"behavior\":\"jump_to\",\"selector\":\"body\",\"dialog_node\":\"node_11_1468608786372\"},\"conditions\":\"#about_VA\",\"description\":null,\"dialog_node\":\"node_1_1487280858924\",\"previous_sibling\":\"node_1_1487280368483\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"Your total due this month is 1200 AED. <br> <li> Utilities, account no. 384293 </li>\",\"Your total due this month is 2600 AED. <br> <li> Phone, account no. 6847384 </li> <li> Utilities, account no. 384293 </li>\",\"Your total due this month is 3200 AED. <br> <li> Phone, account no. 6847384 </li> <li> Utilities, account no. 384293 </li> <li> Home entertainment, account no. 397394 </li>\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#bills\",\"description\":null,\"dialog_node\":\"node_2_1519901414883\",\"previous_sibling\":\"node_1_1519901281716\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":\"Hello! I'm doing good. I'm here to help you. Just say the word.\"},\"parent\":null,\"context\":null,\"metadata\":{},\"next_step\":null,\"conditions\":\"#greetings\",\"description\":null,\"dialog_node\":\"node_7_1468608329601\",\"previous_sibling\":\"node_11_1468608786372\"},{\"type\":\"standard\",\"title\":null,\"output\":{\"text\":{\"values\":[\"Hmm. I'm not sure I can help you. I'll have one of our agents call you in the next 20 minutes.\"],\"selection_policy\":\"sequential\"}},\"parent\":null,\"context\":{\"default_counter\":\"<?$default_counter+1?>\"},\"metadata\":{},\"next_step\":null,\"conditions\":\"anything_else\",\"description\":null,\"dialog_node\":\"node_2_1487280430136\",\"previous_sibling\":\"node_3_1519901471407\"},{\"type\":\"standard\",\"title\":\"Start And Initialize Context\",\"output\":{\"text\":{\"values\":[\"Hi. How can I help you?  \"]}},\"parent\":null,\"context\":{},\"metadata\":{},\"next_step\":null,\"conditions\":\"conversation_start\",\"description\":null,\"dialog_node\":\"Start And Initialize Context\",\"previous_sibling\":null}],\"workspace_id\":\"40ce04fc-cb16-4dcd-a156-d695a68eb925\",\"counterexamples\":[{\"text\":\"aho\"},{\"text\":\"asdasdasda\"},{\"text\":\"asdasidjiwe\"},{\"text\":\"cats are my favorite animal\"},{\"text\":\"when will it be funny\"},{\"text\":\"which color is best for wedding\"}],\"learning_opt_out\":false}"
  },
  {
    "path": "support/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "support/lib/watson-conversation-setup.js",
    "content": "/**\n * Copyright 2017 IBM Corp. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License'); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n\n'use strict';\n\nrequire('dotenv').config({\n  silent: true\n});\n\n/**\n * Setup for Watson Conversation and Discovery.\n *\n * @param {Object} conversationClient - Conversation client\n * @constructor\n */\nfunction WatsonConversationSetup(conversationClient) {\n  this.conversationClient = conversationClient;\n}\n\n/**\n * Validate or create the Conversation workspace.\n * Sets the global workspaceID when done (or global setupError).\n *\n * If a WORKSPACE_ID is specified in the runtime environment,\n * make sure that workspace exists. If no WORKSPACE_ID is\n * specified then try to find it using a lookup by name.\n * Name will be taken from params.default_name unless overridden\n * using the WORKSPACE_NAME environment variable.\n *\n * If a workspace is not found by ID or name, then try to\n * create one from the JSON in the repository. Use the\n * name as mentioned above so future lookup will find what\n * was created.\n *\n * @param {Object} params - Parameter dictionary as follows.\n * @param {String} params.default_name - Name of app, used as default workspace name when needed\n *                                       to create/find\n * @param {Object} params.workspace_json - The workspace JSON to import.\n * @param {function{Error,String}} callback - A callback to capture Error or workspace ID string.\n */\nWatsonConversationSetup.prototype.setupConversationWorkspace = function(params, callback) {\n  let workspaceID;\n\n  this.conversationClient.listWorkspaces(null, (err, data) => {\n    if (err) {\n      console.error('Error during Conversation listWorkspaces(): ', err);\n      callback(new Error('Error. Unable to list workspaces for Conversation: ' + err));\n    } else {\n      const workspaces = data['workspaces'];\n      const validateID = process.env.WORKSPACE_ID;\n      let found = false;\n      if (validateID) {\n        console.log('Validating workspace ID: ', validateID);\n        for (let i = 0, size = workspaces.length; i < size; i++) {\n          if (workspaces[i]['workspace_id'] === validateID) {\n            workspaceID = validateID;\n            found = true;\n            console.log('Found workspace: ', validateID);\n            break;\n          }\n        }\n        if (!found) {\n          callback(new Error(\"Configured WORKSPACE_ID '\" + validateID + \"' not found!\"));\n        } else {\n          callback(null, workspaceID);\n        }\n      } else {\n        // Find by name, because we probably created it earlier (in the if block) and want to use it on restarts.\n        const workspaceName = params.default_name;\n        console.log('Looking for workspace by name: ', workspaceName);\n        for (let i = 0, size = workspaces.length; i < size; i++) {\n          if (workspaces[i]['name'] === workspaceName) {\n            console.log('Found workspace: ', workspaceName);\n            workspaceID = workspaces[i]['workspace_id'];\n            found = true;\n            break;\n          }\n        }\n        if (!found) {\n          console.log('Creating Conversation workspace ', workspaceName);\n          const ws = params.workspace_json;\n          ws['name'] = workspaceName;\n          this.conversationClient.createWorkspace(ws, function(err, ws) {\n            if (err) {\n              callback(new Error('Failed to create Conversation workspace: ' + err));\n            } else {\n              workspaceID = ws['workspace_id'];\n              console.log('Successfully created Conversation workspace');\n              console.log('  Name: ', ws['name']);\n              console.log('  ID:', workspaceID);\n              callback(null, workspaceID);\n            }\n          });\n        } else {\n          callback(null, workspaceID);\n        }\n      }\n    }\n  });\n};\n\nmodule.exports = WatsonConversationSetup;\n"
  },
  {
    "path": "support/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-support\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "support/package.json",
    "content": "{\n  \"name\": \"innovate\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"express\": \"^4.15.3\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"dotenv\": \"^2.0.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "support/server.js",
    "content": "'use strict';\n\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 4000;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}`)\n\nserver.listen(port, function () {\n    console.log('Server running on port: %d', port);\n});\n"
  },
  {
    "path": "transactions/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "transactions/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "transactions/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "transactions/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "transactions/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 3600\n\nEXPOSE 3600\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "transactions/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 3600\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 3600\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "transactions/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst transactions = require('./mongoose/transaction');\r\n\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('*', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\napp.post('/api/transactions/create', function (req, res) {\r\n    var newTransaction = {\r\n        uuid: req.body.uuid,\r\n        amount: req.body.amount,\r\n        currency: req.body.currency,\r\n        description: req.body.description,\r\n        date: req.body.date,\r\n        category: req.body.category\r\n    };\r\n    transactions.create(newTransaction, function (err) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send(err);\r\n            return;\r\n        }\r\n        console.log(\"Transaction created\");\r\n        res.status(200).send({'message': 'Done!'});\r\n    });\r\n});\r\n\r\napp.post('/api/transactions/get', function (req, res) {\r\n    transactions.find({'uuid': req.body.uuid}, function (err, results) {\r\n        if (err) {\r\n            console.log(err);\r\n            res.status(500).send({'err': err});\r\n            return;\r\n        }\r\n        console.log('Fetched ', results);\r\n        res.status(200).send(results);\r\n    });\r\n});\r\n\r\napp.get('/api/transactions/drop', function (req, res) {\r\n    transactions.collection.drop();\r\n    res.status(200).send({'message': 'Done!'});\r\n});\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "transactions/chart/innovate-transactions/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-transactions\nversion: 1.0.0\n"
  },
  {
    "path": "transactions/chart/innovate-transactions/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "transactions/chart/innovate-transactions/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "transactions/chart/innovate-transactions/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "transactions/chart/innovate-transactions/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-userbase\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 3600\n  serviceNodePort: 30200\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "transactions/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-transactions-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-transactions-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"3600:3600\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5864:5864\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-transactions-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-transactions-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-transactions\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-transactions\"\n"
  },
  {
    "path": "transactions/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "transactions/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-transactions\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "transactions/mongoose/transaction.js",
    "content": "const mongoose = require('mongoose');\n\nvar Schema = mongoose.Schema;\nvar Transaction = new Schema({\n    uuid: String,\n    amount: Number,\n    currency: String,\n    description: String,\n    date: String,\n    category: String\n});\n\nmodule.exports = mongoose.model('Transaction', Transaction, \"transactions\");\n"
  },
  {
    "path": "transactions/package.json",
    "content": "{\n  \"name\": \"innovate-transactions\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "transactions/server.js",
    "content": "'use strict';\n\nconst mongoose = require('mongoose');\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 3600;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\n\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\n    connection.onOpen();\n    server.listen(port, function () {\n        console.log('Server running on port: %d', port);\n    });\n});\n"
  },
  {
    "path": "userbase/.cfignore",
    "content": ".git/\nnode_modules/\ntest/\nvcap-local.js\n"
  },
  {
    "path": "userbase/.dockerignore",
    "content": "node_modules/\ntest/\n.bluemix/\n"
  },
  {
    "path": "userbase/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# other\n.DS_Store\nlicense_accepted\n"
  },
  {
    "path": "userbase/.ibm-project",
    "content": "{\"build-release-ready\":true,\"build-debug-ready\":false,\"deploy-image\":\"\",\"chart-path\":\"\",\"ibm-cluster\":\"\"}"
  },
  {
    "path": "userbase/Dockerfile",
    "content": "FROM ibmcom/ibmnode:latest\nLABEL maintainer=\"***REMOVED***\"\n\n#RUN apt-get install -y nodejs npm\n\nWORKDIR /app\n# Install app dependencies\nCOPY . /app\nRUN cd /app; npm install; npm prune --production\nENV NODE_ENV production\nENV PORT 4200\n\nEXPOSE 4200\nCMD [ \"npm\",\"start\" ]\n"
  },
  {
    "path": "userbase/Dockerfile-tools",
    "content": "FROM ibmcom/ibmnode\n\nENV PORT 4200\n\nWORKDIR \"/app\"\n\n# Bundle app source\nCOPY . /app\n\nEXPOSE 4200\n\nCMD [\"/bin/bash\"]\n\nARG bx_dev_user=root\nARG bx_dev_userid=1000\nRUN BX_DEV_USER=$bx_dev_user\nRUN BX_DEV_USERID=$bx_dev_userid\nRUN if [ $bx_dev_user != \"root\" ]; then useradd -ms /bin/bash -u $bx_dev_userid $bx_dev_user; fi\n"
  },
  {
    "path": "userbase/app.js",
    "content": "'use strict';\r\n\r\nconst express = require('express');\r\nconst bodyParser = require('body-parser');\r\nconst dateFormat = require('dateformat');\r\nconst request = require('request');\r\nconst ip = require('ip');\r\n\r\nconst config = require(`${__dirname}/config`)[process.env.NODE_ENV];\r\nvar app = express();\r\n\r\napp.use(bodyParser.json());\r\n\r\napp.all('*', function (req, res, next) {\r\n    res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n    res.header(\"Access-Control-Allow-Headers\", \"*\");\r\n    next();\r\n});\r\n\r\nlet basePath = 'http://localhost';\r\nif (process.env.NODE_ENV!='development') basePath = process.env.BASE_PATH;\r\n\r\nconsole.log('Base Path: ', basePath)\r\n\r\nrequire('./populate.js')(request, basePath, config.ports, dateFormat);\r\n\r\nmodule.exports = app;\r\n"
  },
  {
    "path": "userbase/chart/innovate-userbase/Chart.yaml",
    "content": "apiVersion: v1\ndescription: A Helm chart for innovate bank portal\nname: innovate-userbase\nversion: 1.0.0\n"
  },
  {
    "path": "userbase/chart/innovate-userbase/templates/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: \"{{  .Chart.Name }}-deployment\"\n  labels:\n    chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}'\nspec:\n  replicas: {{ .Values.replicaCount }}\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}\n  template:\n    metadata:\n      labels:\n        app: \"{{  .Chart.Name }}-selector\"\n    spec:\n      containers:\n      - name: \"{{  .Chart.Name  }}\"\n        image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n        imagePullPolicy: {{ .Values.image.pullPolicy }}\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: {{ .Values.service.servicePort }}\n          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}}\n          periodSeconds: {{ .Values.livenessProbe.periodSeconds}}\n        resources:\n          requests:\n            cpu: \"{{ .Values.image.resources.requests.cpu }}\"\n            memory: \"{{ .Values.image.resources.requests.memory }}\"\n        env:\n          - name: PORT\n            value : \"{{ .Values.service.servicePort }}\"\n"
  },
  {
    "path": "userbase/chart/innovate-userbase/templates/hpa.yaml",
    "content": "{{ if .Values.hpa.enabled }}\napiVersion: autoscaling/v2alpha1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: \"{{ .Chart.Name }}-hpa-policy\"\n  namespace: \nspec:\n  scaleTargetRef:\n    apiVersion: apps/v2alpha1\n    kind: Deployment\n    name: \"{{ .Chart.Name }}-deployment\"\n  minReplicas: {{ .Values.hpa.minReplicas }}\n  maxReplicas: {{ .Values.hpa.maxReplicas }}\n  metrics:\n  - type: Resource\n    resource:\n      name: cpu\n      targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }}\n  - type: Resource\n    resource:\n      name: memory\n      targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }}\n{{ end }}"
  },
  {
    "path": "userbase/chart/innovate-userbase/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n    prometheus.io/scrape: 'true'\n  name: \"{{  .Chart.Name }}\"\n  labels:\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\"\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n  - port: {{ .Values.service.servicePort }}\n    nodePort: {{ .Values.service.serviceNodePort }}\n  selector:\n    app: \"{{  .Chart.Name }}-selector\"\n"
  },
  {
    "path": "userbase/chart/innovate-userbase/values.yaml",
    "content": "# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\nreplicaCount: 1\nrevisionHistoryLimit: 3\nimage:\n  repository: mycluster.icp:8500/default/innovate-userbase\n  tag: v1.0.0\n  pullPolicy: Always\n  resources:\n    requests:\n      cpu: 500m\n      memory: 512Mi\nlivenessProbe:\n  initialDelaySeconds: 3000\n  periodSeconds: 1000\nservice:\n  name: Node\n  type: NodePort\n  servicePort: 4100\n  serviceNodePort: 30050\nhpa:\n  enabled: false\n  minReplicas: 2\n  maxReplicas: 3\n  metrics:\n    cpu:\n      targetAverageUtilization: 80\n    memory:\n      targetAverageUtilization: 80\nservices:\n"
  },
  {
    "path": "userbase/cli-config.yml",
    "content": "# The IBM version of this configuration\nversion : 0.0.3\n\n# The container name used for the run container\ncontainer-name-run : \"innovate-userbase-run\"\n# The container name used for the tools container\ncontainer-name-tools : \"innovate-userbase-tools\"\n\n# The project root on the host for the run container to mount to container-path-run\nhost-path-run : .\n# The project root on the host for the tools container to mount to container-path-tools\nhost-path-tools : .\n\n# The project root in the run container to mount to host-path-run\ncontainer-path-run : \"/app\"\n# The project root in the tools container that will be mounted to host-path-tools\ncontainer-path-tools : \"/app\"\n\n# The list of additional mounts between the host and the run container in the form [host_path:container_path]\ncontainer-mounts-run:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n# The list of additional mounts between the host and the tools container in the form [host_path:container_path]\ncontainer-mounts-tools:\n   - \"./node_modules_linux\": \"/app/node_modules\"\n\n# The port mappings between the host and the container in the form [host:container]\ncontainer-port-map : \"4200:4200\"\n# The port mappings between the host and the container for the debug port in the form [host:container]\ncontainer-port-map-debug : \"5870:5870\"\n\n# The name for the dockerfile for the run container\ndockerfile-run : \"Dockerfile\"\n# The name for the dockerfile for the tools container\ndockerfile-tools : \"Dockerfile-tools\"\n\n# The name of image to create from dockerfile-run\nimage-name-run : \"innovate-userbase-run\"\n# The name of image to create from dockerfile-tools\nimage-name-tools : \"innovate-userbase-tools\"\n\n# The command to build the code and docker image for RUN\nbuild-cmd-run : \"npm install\"\n# The command to execute tests for the code in the tools container\ntest-cmd : \"npm run test\"\n# The command to build the code and docker image for DEBUG\nbuild-cmd-debug : \"npm install\"\n\n# The command to run the code in the run container\nrun-cmd : \"\"\n# The command to execute debug of the code in the tools container\ndebug-cmd : \"npm run debug\"\n# The command to stop the code\nstop-cmd : \"npm stop\"\n\n# The relative path to the helm chart used for Kubernetes deployment\nchart-path: \"chart/innovate-userbase\"\ndeploy-target: \"container\"\ndeploy-image-target: \"mycluster.icp:8500/default/innovate-userbase\"\n"
  },
  {
    "path": "userbase/config.js",
    "content": "module.exports = {\n  development: {\n    ports: {\n      portal: 3100,\n      authentication: 3200,\n      accounts: 3400,\n      transactions: 3600,\n      bills: 3800,\n      support: 4000,\n      userbase: 4100\n    }\n  },\n  production: {\n    ports: {\n      portal: 30200,\n      authentication: 30100,\n      accounts: 30120,\n      transactions: 30140,\n      bills: 30160,\n      support: 30180,\n      userbase: 30050\n    }\n  }\n};\n"
  },
  {
    "path": "userbase/idt.js",
    "content": "'use strict'\n\n/*\n *  Wrapper for the idt (IBM Developer Tools) command.\n *  Run with the same arguments as `idt`, e.g.\n *    `node idt.js build` -> `idt build`.\n *  If `idt` isn't installed, this will prompt you to install. Or you can run\n *  `node idt.js install` to automatically install idt and any other\n *  required dependencies (e.g. docker, git, kubernetes, helm).\n *\n */\n\nconst fs = require('fs');\nconst process = require('process');\nconst cp = require('child_process');\nconst request = require('request');\nconst path = require('path');\n\nconst chalk = require('chalk');\n\nconst node = process.execPath;\n// Array of args passed to idt.js.\nconst args = process.argv.slice(2);\nlet win = (process.platform === 'win32');\n\n// Either install idt or run idt + args.\nif (args.includes('install')) {\n  downloadInstaller();\n} else {\n  // TODO(gib): Check for idt once this works in scripts:\n  // const checkCmd = win ? 'where idt' : 'which idt';\n  const checkCmd = 'bx plugin show dev';\n  let hasIDT = false;\n  try {\n    console.log(chalk.blue('Checking for idt'));\n    cp.execSync(checkCmd); // Don't inherit stdio, we don't want to print the output.\n    hasIDT = true; // If we didn't have idt, the previous command would have thrown.\n  } catch (e) {\n    const prompt = require('prompt-confirm');\n    new prompt({ name: 'install',\n      message: 'IDT not found, do you want to install it? y/N',\n      default: false\n    }).ask((answer) => {\n      if (answer) {\n        downloadInstaller(() => runIDT(args));\n      } else {\n        console.error(chalk.red(`Not installing idt, so not running: idt ${args.join(' ')}`));\n      }\n    });\n  }\n  if (hasIDT) runIDT(args);\n}\n\n// Run IDT with whatever args we were given.\nfunction runIDT(args) {\n  const cmd = 'bx dev ' + args.join(' ');\n  console.log(chalk.blue('Running:'), cmd);\n  cp.execSync(cmd, {stdio: 'inherit'});\n}\n\n// Download the IDT installer script and trigger runInstaller().\nfunction downloadInstaller(cb) {\n  const url = win ?\n    'https://ibm.biz/yeoman-idt-win-install' :\n    'http://ibm.biz/yeoman-idt-install';\n\n  const fileName = url.split('/').pop()\n\n  console.log(chalk.blue('Downloading installer from:'), url);\n\n  const file = fs.createWriteStream(fileName);\n\n  request\n    .get({url, followAllRedirects: true})\n    .on('error', (err) => { console.error(err); })\n    .pipe(file)\n    .on('finish', () => runInstaller(fileName, cb));\n}\n\n// Run the installer script and trigger optional callback (cb).\nfunction runInstaller(fileName, cb) {\n  const shell = win ? 'powershell.exe' : 'bash';\n\n  const filePath = path.resolve(__dirname, fileName);\n  console.log(`Now running: ${shell} ${filePath}`);\n\n  cp.spawnSync(shell, [filePath], {stdio: 'inherit'});\n  typeof cb === 'function' && cb();\n}\n"
  },
  {
    "path": "userbase/manifest.yml",
    "content": "---\napplications:\n- instances: 1\n  timeout: 180\n  name: innovate-userbase\n  buildpack: sdk-for-nodejs\n  command: npm start\n  memory: 512M\n"
  },
  {
    "path": "userbase/package.json",
    "content": "{\n  \"name\": \"innovate-userbase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Innovate: Digital Bank\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"^6.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server.js\",\n    \"start:cluster\": \"sl-run server/server.js\",\n    \"debug\": \"node --debug server/server.js\",\n    \"build\": \"npm run build:idt\",\n    \"idt:build\": \"node idt.js build\",\n    \"idt:test\": \"node idt.js test\",\n    \"idt:debug\": \"node idt.js debug\",\n    \"idt:run\": \"node idt.js run\",\n    \"idt:deploy\": \"node idt.js deploy\",\n    \"idt:install\": \"node idt.js install\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.17.2\",\n    \"dateformat\": \"^3.0.3\",\n    \"dotenv\": \"^2.0.0\",\n    \"express\": \"^4.15.3\",\n    \"ip\": \"^1.1.5\",\n    \"mongoose\": \"^5.0.0-rc1\",\n    \"request\": \"^2.83.0\",\n    \"strong-supervisor\": \"^6.2.0\",\n    \"uuid\": \"^3.1.0\",\n    \"watson-developer-cloud\": \"^2.40.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.0.0\",\n    \"chalk\": \"^1.1.3\",\n    \"mocha\": \"^3.4.2\",\n    \"nyc\": \"^10.3.2\",\n    \"prompt-confirm\": \"^1.2.0\",\n    \"proxyquire\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "userbase/populate.js",
    "content": "module.exports = function (request, basePath, ports, dateFormat) {\n    var randomEntries = {\n        bills: [\n            {\n                category: 'utilities',\n                entity: 'DEWA'\n            },\n            {\n                category: 'home_entertainment',\n                entity: 'Etisalat'\n            },\n            {\n                category: 'mobile_phone',\n                entity: 'Du'\n            },\n            {\n                category: 'credit_card',\n                entity: 'Innovate'\n            }\n        ],\n        transactions: [\n            {\n                category: 'groceries',\n                description: [\n                    'Carrefour',\n                    'Lulu Hypermarket',\n                    'Geant',\n                    'Waitrose',\n                    'Spinneys'\n                ]\n            },\n            {\n                category: 'eating_out',\n                description: [\n                    'Krush Burgers',\n                    'Clinton Baking St',\n                    'Mamaeesh',\n                    'Starbucks',\n                    'Costa Coffee',\n                    'Blaze Burgers',\n                    'Cheesecake Factory'\n                ]\n            },\n            {\n                category: 'transport',\n                description: [\n                    'Uber',\n                    'Careem'\n                ]\n            },\n            {\n                category: 'bills',\n                description: [\n                    'Utilities',\n                    'Home entertainment',\n                    'Phone',\n                    'Credit card'\n                ]\n            },\n            {\n                category: 'expenses',\n                description: [\n                    'Municipality fee',\n                    'VAT',\n                    'Shopping',\n                    'Electronics',\n                    'Shoes'\n                ]\n            },\n            {\n                category: 'cash',\n                description: [\n                    'Withdrawal',\n                    'Transfer'\n                ]\n            },\n            {\n                category: 'holidays',\n                description: [\n                    'Flight ticket',\n                    'Hotel booking'\n                ]\n            }\n        ]\n    };\n\n    function createTransaction(uuid) {\n        let amount = Math.floor(Math.random() * Math.floor(1200)) + '';\n        let date = dateFormat(new Date(), \"mm, dd, yyyy\");\n        let randomCategoryIndex = Math.floor(Math.random() * Math.floor(randomEntries.transactions.length));\n        let randomDescriptionIndex = Math.floor(Math.random() * Math.floor(randomEntries.transactions[randomCategoryIndex].description.length));\n        var body = {\n            uuid: uuid,\n            amount: amount,\n            currency: 'AED',\n            category: randomEntries.transactions[randomCategoryIndex].category,\n            description: randomEntries.transactions[randomCategoryIndex].description[randomDescriptionIndex],\n            date: date\n        };\n        console.log('Adding transaction: ');\n        console.log(body);\n        var options = {\n            method: 'POST',\n            uri: `http://${basePath}:${ports.transactions}${process.env.CREATE_TRANSACTION_ENDPOINT}`,\n            body: body,\n            json: true\n        };\n        request.post(options, function (err, response, body) {\n            return;\n        });\n    }\n\n    function createBill(uuid) {\n        let randomIndex = Math.floor(Math.random() * Math.floor(randomEntries.bills.length));\n        let amount = Math.floor(Math.random() * Math.floor(1200)) + '';\n        let date = dateFormat(new Date(), \"mm, dd, yyyy\");\n        let account_no = Math.floor(Math.random() * 90000000) + '';\n        var body = {\n            uuid: uuid,\n            category: randomEntries.bills[randomIndex].category,\n            entity: randomEntries.bills[randomIndex].entity,\n            amount: amount,\n            date: date,\n            account_no: account_no\n        };\n        console.log('Adding bill: ');\n        console.log(body);\n        var options = {\n            method: 'POST',\n            uri: `http://${basePath}:${ports.bills}${process.env.UPSERT_BILL_ENDPOINT}`,\n            body: body,\n            json: true\n        };\n        request.post(options, function (err, response, body) {\n            return;\n        });\n    }\n\n    function dropBills() {\n        var options = {\n            method: 'GET',\n            uri: `http://${basePath}:${ports.bills}${process.env.DROP_BILLS_ENDPOINT}`,\n            json: true\n        };\n        request.get(options, function (err, response, body) {\n            return;\n        });\n    }\n\n    function dropTransactions() {\n        var options = {\n            method: 'GET',\n            uri: `http://${basePath}:${ports.transactions}${process.env.DROP_TRANSACTIONS_ENDPOINT}`,\n            json: true\n        };\n        request.get(options, function (err, response, body) {\n            return;\n        });\n    }\n\n    function dropAccounts() {\n        var options = {\n            method: 'GET',\n            uri: `http://${basePath}:${ports.accounts}${process.env.DROP_ACCOUNTS_ENDPOINT}`,\n            json: true\n        };\n        request.get(options, function (err, response, body) {\n            return;\n        });\n    }\n\n    function populate() {\n        console.log('Populating');\n        return new Promise(function (resolve, reject) {\n            var options = {\n                method: 'GET',\n                uri: `http://${basePath}:${ports.authentication}${process.env.GET_USERS_ENDPOINT}`,\n                json: true\n            };\n            request.get(options, function (err, response, body) {\n                if (err) {\n                    reject(err);\n                }\n                resolve(body);\n            });\n        })\n        .then(function (users) {\n            console.log(users);\n            for (index in users) {\n                createBill(users[index].uuid);\n                createTransaction(users[index].uuid);\n            }\n            return;\n        })\n        .catch(function (err) {\n            console.log('Failed to retrieve users; ', err);\n            return;\n        });\n    }\n\n    function reset() {\n        console.log('Resetting');\n        dropAccounts();\n        dropTransactions();\n        dropBills();\n        return;\n    }\n\n    function init() {\n        setInterval(reset, 3600000);\n        setInterval(populate, 180000);\n    }\n\n    reset();\n    populate();\n    init();\n\n};\n"
  },
  {
    "path": "userbase/server.js",
    "content": "'use strict';\n\nconst mongoose = require('mongoose');\nrequire('dotenv').config({silent: true, path: `${__dirname}/.env`});\n\nvar server = require('./app');\nvar port = 4100;\n\nconsole.log(`Running on ${process.env.BASE_PATH}:${port}, connecting to ${process.env.MONGO_URL}`)\n\nmongoose.connect(process.env.MONGO_URL, function (ignore, connection) {\n    connection.onOpen();\n    server.listen(port, function () {\n        console.log('Server running on port: %d', port);\n    });\n});\n"
  }
]