Added new authentication methods using authKey
and cookies. Also now handles changes to base url for use with reverse proxies
This commit is contained in:
parent
8f3e7578e7
commit
588f90feb6
@ -1 +1,2 @@
|
|||||||
VITE_EO_SERVICES_URL=http://localhost:3000
|
VITE_EO_SERVICES_URL=http://localhost:3000
|
||||||
|
VITE_ROUTER_BASE=/
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
VITE_EO_SERVICES_URL=https://eo-services.mortons.site/api
|
VITE_EO_SERVICES_URL=https://eo-services.mortons.site
|
||||||
|
VITE_ROUTER_BASE=/eo-services
|
||||||
|
|||||||
@ -9,7 +9,8 @@ RUN npm run build
|
|||||||
|
|
||||||
# production stage
|
# production stage
|
||||||
FROM nginx:stable-alpine as production-stage
|
FROM nginx:stable-alpine as production-stage
|
||||||
COPY --from=build-stage /app/dist /app
|
COPY --from=build-stage /app/dist /app/eo-services
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY headers.js /etc/nginx/headers.js
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
6
headers.js
Normal file
6
headers.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// /etc/nginx/headers.js
|
||||||
|
function headers_json(r) {
|
||||||
|
return JSON.stringify(r.headersIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {headers_json};
|
||||||
@ -1,6 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<%- baseHref %>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|||||||
33
nginx.conf
33
nginx.conf
@ -1,3 +1,5 @@
|
|||||||
|
load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
|
||||||
|
|
||||||
user nginx;
|
user nginx;
|
||||||
worker_processes 1;
|
worker_processes 1;
|
||||||
error_log /var/log/nginx/error.log warn;
|
error_log /var/log/nginx/error.log warn;
|
||||||
@ -8,20 +10,41 @@ events {
|
|||||||
http {
|
http {
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
js_import headers.js;
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
js_set $headers_json headers.headers_json;
|
||||||
|
|
||||||
|
# Using custom log format here
|
||||||
|
log_format main '$remote_addr'
|
||||||
|
'\t$remote_user'
|
||||||
|
'\t$time_local'
|
||||||
|
'\t$request'
|
||||||
|
'\t$status'
|
||||||
|
'\t$headers_json';
|
||||||
|
|
||||||
|
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
# '$status $body_bytes_sent "$http_referer" '
|
||||||
|
# '"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
access_log /var/log/nginx/access.log main;
|
access_log /var/log/nginx/access.log main;
|
||||||
sendfile on;
|
sendfile on;
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
location / {
|
|
||||||
|
location /eo-services {
|
||||||
|
mirror /mirror;
|
||||||
root /app;
|
root /app;
|
||||||
index index.html;
|
index index.html;
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /eo-services/index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mirror {
|
||||||
|
internal;
|
||||||
|
proxy_pass https://eo-services.mortons.site/api/auth;
|
||||||
|
proxy_set_header X-Original-URI $request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
error_page 500 502 503 504 /50x.html;
|
||||||
location = /50x.html {
|
location = /50x.html {
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
|
|||||||
1154
package-lock.json
generated
1154
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,11 +4,12 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
|
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
|
||||||
"format": "prettier . --write"
|
"format": "prettier . --write",
|
||||||
|
"push": "docker buildx bake --push"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||||
@ -17,9 +18,11 @@
|
|||||||
"d3": "^7.8.5",
|
"d3": "^7.8.5",
|
||||||
"d3-sankey": "^0.12.3",
|
"d3-sankey": "^0.12.3",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
|
"vite-plugin-html": "^3.2.0",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
"vue-router": "^4.1.5",
|
"vue-router": "^4.1.5",
|
||||||
"vue-sidebar-menu": "^5.2.8"
|
"vue-sidebar-menu": "^5.2.8",
|
||||||
|
"vue3-cookies": "^1.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/d3-sankey": "^0.12.1",
|
"@types/d3-sankey": "^0.12.1",
|
||||||
|
|||||||
134
src/App.vue
134
src/App.vue
@ -1,102 +1,18 @@
|
|||||||
<script>
|
<script>
|
||||||
import { h, markRaw } from "vue";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
||||||
import { SidebarMenu } from "vue-sidebar-menu";
|
|
||||||
import "vue-sidebar-menu/dist/vue-sidebar-menu.css";
|
|
||||||
|
|
||||||
const separator = {
|
|
||||||
template: '<hr style="border-color: rgba(0, 0, 0, 0.1); margin: 20px;">',
|
|
||||||
}
|
|
||||||
|
|
||||||
const faIcon = (props) => {
|
|
||||||
return {
|
|
||||||
element: markRaw({
|
|
||||||
render: () => h("div", [h(FontAwesomeIcon, { size: "lg", ...props })]),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
|
||||||
SidebarMenu,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: [
|
|
||||||
{
|
|
||||||
header: "Services",
|
|
||||||
hiddenOnCollapse: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "/",
|
|
||||||
title: "Home",
|
|
||||||
icon: faIcon({ icon: "fa-solid fa-house" }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "/about",
|
|
||||||
title: "About",
|
|
||||||
icon: faIcon({ icon: "fa-solid fa-question" }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: markRaw(separator),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "/referenceId",
|
|
||||||
title: "Contacts Lookup",
|
|
||||||
icon: faIcon({ icon: "fa-solid fa-rectangle-list" }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "/interactionsFlow",
|
|
||||||
title: "Interactions Flow",
|
|
||||||
icon: faIcon({ icon: "fa-solid fa-route" }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "/customerAccount/12345",
|
|
||||||
title: "Customer Account Example",
|
|
||||||
icon: faIcon({ icon: "fa-solid fa-id-card" }),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
collapsed: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.onResize();
|
|
||||||
window.addEventListener("resize", this.onResize);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onResize() {
|
|
||||||
if (window.innerWidth <= 767) {
|
|
||||||
this.isOnMobile = true;
|
|
||||||
this.collapsed = true;
|
|
||||||
} else {
|
|
||||||
this.isOnMobile = false;
|
|
||||||
this.collapsed = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<sidebar-menu
|
<div class="flex-container">
|
||||||
v-model:collapsed="collapsed"
|
|
||||||
:menu="menu"
|
<router-view class="view sidebar" name="SideBarView"></router-view>
|
||||||
:show-one-child="true"
|
|
||||||
/>
|
<div class="flex-child">
|
||||||
<div id="services" :class="[{ collapsed: collapsed }]">
|
<router-view class="view main-content"></router-view>
|
||||||
<div class="services">
|
|
||||||
<div class="container">
|
|
||||||
<router-view></router-view>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <div>
|
|
||||||
<router-link to="/">Home</router-link>
|
|
||||||
<router-link to="/about">About</router-link>
|
|
||||||
<router-link to="/referenceId">Reference ID Tracker</router-link>
|
|
||||||
<router-link to="/interactionsFlow">Interactions Flow</router-link>
|
|
||||||
<router-link to="/customerAccount">Customer Account</router-link>
|
|
||||||
</div> -->
|
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600");
|
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600");
|
||||||
@ -114,35 +30,17 @@ body {
|
|||||||
color: #262626;
|
color: #262626;
|
||||||
}
|
}
|
||||||
|
|
||||||
#services {
|
.flex-container {
|
||||||
padding-left: 290px;
|
display: flex;
|
||||||
transition: 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#services.collapsed {
|
|
||||||
padding-left: 65px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#services.onmobile {
|
|
||||||
padding-left: 65px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-overlay {
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: #000;
|
|
||||||
opacity: 0.5;
|
|
||||||
z-index: 900;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.services {
|
.flex-child {
|
||||||
padding: 50px;
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
border: 2px solid yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
// .flex-child:first-child {
|
||||||
max-width: 900px;
|
// margin-right: 20px;
|
||||||
}
|
// } </style>
|
||||||
</style>
|
|
||||||
|
|||||||
@ -1,44 +1,57 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import HomeView from "../views/HomeView.vue";
|
import HomeView from "../views/HomeView.vue";
|
||||||
import ReferenSearchByReferenceViewceID from "../views/SearchByReferenceView.vue";
|
import AboutView from "../views/AboutView.vue";
|
||||||
|
import DebugFrameView from "../views/DebugFrameView.vue";
|
||||||
|
import SideBarView from "../views/SideBarView.vue";
|
||||||
|
import SearchByReferenceView from "../views/SearchByReferenceView.vue";
|
||||||
import InteractionsFlowView from "../views/InteractionsFlowView.vue";
|
import InteractionsFlowView from "../views/InteractionsFlowView.vue";
|
||||||
import CustomerAccountView from "../views/CustomerAccountView.vue";
|
import CustomerAccountView from "../views/CustomerAccountView.vue";
|
||||||
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "home",
|
name: "home",
|
||||||
component: HomeView,
|
components: { default: HomeView, SideBarView: SideBarView },
|
||||||
|
props: { default: false, SideBarView: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/about",
|
path: "/about",
|
||||||
name: "about",
|
name: "about",
|
||||||
// route level code-splitting
|
components: { default: AboutView, SideBarView: SideBarView },
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
props: { default: false, SideBarView: true }
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/referenceId",
|
path: "/referenceId",
|
||||||
name: "referenceId",
|
name: "referenceId",
|
||||||
component: ReferenSearchByReferenceViewceID,
|
components: { default: SearchByReferenceView, SideBarView: SideBarView },
|
||||||
|
props: { default: route => ({ sessionIdentifier: route.query._sessionIdentifier }) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/interactionsFlow",
|
path: "/interactionsFlow",
|
||||||
name: "interactionsFlow",
|
name: "interactionsFlow",
|
||||||
component: InteractionsFlowView,
|
components: { default: InteractionsFlowView, SideBarView: SideBarView },
|
||||||
|
props: { default: route => ({ sessionIdentifier: route.query._sessionIdentifier }) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/customerAccount/:accountNumber",
|
path: "/customerAccount/:accountNumber",
|
||||||
name: "customerAccount",
|
name: "customerAccount",
|
||||||
component: CustomerAccountView,
|
component: CustomerAccountView,
|
||||||
props: true,
|
components: { default: CustomerAccountView, SideBarView: SideBarView },
|
||||||
|
props: { default: true, SideBarView: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/debug",
|
||||||
|
name: "debug",
|
||||||
|
component: DebugFrameView,
|
||||||
|
components: { default: DebugFrameView },
|
||||||
|
props: { default: true }
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
|
base: `${import.meta.env.VITE_ROUTER_BASE}`,
|
||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
23
src/views/DebugFrameView.vue
Normal file
23
src/views/DebugFrameView.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script>
|
||||||
|
import { useCookies } from "vue3-cookies";
|
||||||
|
const { cookies } = useCookies();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DebugFrameView",
|
||||||
|
|
||||||
|
data() {
|
||||||
|
|
||||||
|
return {
|
||||||
|
route : JSON.stringify(this.$route, null, 2),
|
||||||
|
cookies : JSON.stringify(cookies.keys(), null, 2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<h1>Adaptive Frame Debug</h1>
|
||||||
|
<h2>Route information</h2>
|
||||||
|
<div>{{ route }}</div>
|
||||||
|
<h2>Cookie information</h2>
|
||||||
|
<div>{{ cookies }}</div>
|
||||||
|
</template>
|
||||||
@ -11,8 +11,5 @@
|
|||||||
>
|
>
|
||||||
Integration.
|
Integration.
|
||||||
</p>
|
</p>
|
||||||
<h2>Services Available</h2>
|
|
||||||
<h3><a href="/referenceId">Reference ID</a></h3>
|
|
||||||
<p>/referenceId</p>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -5,6 +5,12 @@ import * as d3 from "d3";
|
|||||||
import * as align from "d3-sankey";
|
import * as align from "d3-sankey";
|
||||||
import { sankey, sankeyLinkHorizontal } from "d3-sankey";
|
import { sankey, sankeyLinkHorizontal } from "d3-sankey";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import ErrorMessage from "../components/ErrorMessage.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
username: { type: String, default: "" },
|
||||||
|
sessionIdentifier: { type: String, default: "" }
|
||||||
|
});
|
||||||
|
|
||||||
const filterOptions = ["Channel", "SubChannel", "Queue", "Outcome"];
|
const filterOptions = ["Channel", "SubChannel", "Queue", "Outcome"];
|
||||||
const multiSelected = ref(filterOptions);
|
const multiSelected = ref(filterOptions);
|
||||||
@ -22,29 +28,39 @@ function fetchData() {
|
|||||||
//clear errors
|
//clear errors
|
||||||
errorMessage.value = null;
|
errorMessage.value = null;
|
||||||
|
|
||||||
fetch(
|
var authKey;
|
||||||
`${import.meta.env.VITE_EO_SERVICES_URL}/api/interactions-flow?filter=${
|
|
||||||
multiSelected.value
|
if (props.sessionIdentifier.length > 0) {
|
||||||
}`,
|
authKey = props.sessionIdentifier;
|
||||||
{
|
} else if (props.username.length > 0) {
|
||||||
credentials: "include", // fetch won't send cookies unless you set credentials
|
authKey = props.username;
|
||||||
}
|
} else {
|
||||||
)
|
errorMessage.value = "_sessionIdentifier or username must be passed as query params."
|
||||||
.then((response) => {
|
}
|
||||||
// check for error response
|
if (authKey) {
|
||||||
if (!response.ok) {
|
fetch(
|
||||||
// get error message from body or default to response statusText
|
`${import.meta.env.VITE_EO_SERVICES_URL}/api/interactions-flow?filter=${multiSelected.value
|
||||||
const error = response.data || response.statusText;
|
}&authKey=${authKey}`,
|
||||||
return Promise.reject(error);
|
{
|
||||||
|
credentials: "include", // fetch won't send cookies unless you set credentials
|
||||||
}
|
}
|
||||||
response.json().then((data) => {
|
)
|
||||||
generateSankey(data);
|
.then((response) => {
|
||||||
|
// check for error response
|
||||||
|
if (!response.ok) {
|
||||||
|
// get error message from body or default to response statusText
|
||||||
|
const error = response.data || response.statusText;
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
response.json().then((data) => {
|
||||||
|
generateSankey(data);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
errorMessage.value = error;
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
errorMessage.value = error;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSankey(data) {
|
function generateSankey(data) {
|
||||||
@ -80,9 +96,9 @@ function generateSankey(data) {
|
|||||||
.nodeId((d) => d.name)
|
.nodeId((d) => d.name)
|
||||||
.nodeAlign(
|
.nodeAlign(
|
||||||
align[
|
align[
|
||||||
`sankey${alignSelected.value[0].toUpperCase()}${alignSelected.value.slice(
|
`sankey${alignSelected.value[0].toUpperCase()}${alignSelected.value.slice(
|
||||||
1
|
1
|
||||||
)}`
|
)}`
|
||||||
]
|
]
|
||||||
) // d3.sankeyLeft, etc.
|
) // d3.sankeyLeft, etc.
|
||||||
.nodeWidth(15)
|
.nodeWidth(15)
|
||||||
@ -154,10 +170,10 @@ function generateSankey(data) {
|
|||||||
linkColor === "source-target"
|
linkColor === "source-target"
|
||||||
? (d) => `url(#${d.uid})`
|
? (d) => `url(#${d.uid})`
|
||||||
: linkColor === "source"
|
: linkColor === "source"
|
||||||
? (d) => color(d.source.category)
|
? (d) => color(d.source.category)
|
||||||
: linkColor === "target"
|
: linkColor === "target"
|
||||||
? (d) => color(d.target.category)
|
? (d) => color(d.target.category)
|
||||||
: linkColor
|
: linkColor
|
||||||
)
|
)
|
||||||
.attr("stroke-width", (d) => Math.max(1, d.width));
|
.attr("stroke-width", (d) => Math.max(1, d.width));
|
||||||
|
|
||||||
@ -194,6 +210,7 @@ function generateSankey(data) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="chart"></div>
|
<div id="chart"></div>
|
||||||
|
<ErrorMessage v-if="errorMessage" :message="errorMessage" />
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
@ -5,6 +5,11 @@ import ContactTable from "../components/ContactTable.vue";
|
|||||||
import ContactsSummary from "../components/ContactsSummary.vue";
|
import ContactsSummary from "../components/ContactsSummary.vue";
|
||||||
import ErrorMessage from "../components/ErrorMessage.vue";
|
import ErrorMessage from "../components/ErrorMessage.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
username: { type: String, default: "" },
|
||||||
|
sessionIdentifier: { type: String, default: "" }
|
||||||
|
});
|
||||||
|
|
||||||
const referenceId = ref("");
|
const referenceId = ref("");
|
||||||
const contactData = ref(null);
|
const contactData = ref(null);
|
||||||
const errorMessage = ref(null);
|
const errorMessage = ref(null);
|
||||||
@ -17,29 +22,40 @@ function fetchData() {
|
|||||||
//clear errors
|
//clear errors
|
||||||
errorMessage.value = null;
|
errorMessage.value = null;
|
||||||
contactData.value = null;
|
contactData.value = null;
|
||||||
fetch(
|
|
||||||
`${
|
var authKey;
|
||||||
import.meta.env.VITE_EO_SERVICES_URL
|
|
||||||
}/api/unified-data-gateway?referenceId=${referenceId.value}`,
|
if (props.sessionIdentifier.length > 0) {
|
||||||
{
|
authKey = props.sessionIdentifier;
|
||||||
credentials: "include", // fetch won't send cookies unless you set credentials
|
} else if (props.username.length > 0) {
|
||||||
}
|
authKey = props.username;
|
||||||
)
|
} else {
|
||||||
.then((response) => {
|
errorMessage.value = "_sessionIdentifier or username must be passed as query params."
|
||||||
// check for error response
|
}
|
||||||
if (!response.ok) {
|
if (authKey) {
|
||||||
// get error message from body or default to response statusText
|
fetch(
|
||||||
const error = response.data || response.statusText;
|
`${import.meta.env.VITE_EO_SERVICES_URL
|
||||||
return Promise.reject(error);
|
}/api/unified-data-gateway?referenceId=${referenceId.value}&authKey=${authKey}`,
|
||||||
|
{
|
||||||
|
credentials: "include", // fetch won't send cookies unless you set credentials
|
||||||
}
|
}
|
||||||
response.json().then((data) => {
|
)
|
||||||
contactData.value = data;
|
.then((response) => {
|
||||||
|
// check for error response
|
||||||
|
if (!response.ok) {
|
||||||
|
// get error message from body or default to response statusText
|
||||||
|
const error = response.data || response.statusText;
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
response.json().then((data) => {
|
||||||
|
contactData.value = data;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
errorMessage.value = error;
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
errorMessage.value = error;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
@ -47,22 +63,14 @@ function fetchData() {
|
|||||||
<h2>Search Criteria</h2>
|
<h2>Search Criteria</h2>
|
||||||
<div>
|
<div>
|
||||||
<label for="referenceId">Reference ID: </label>
|
<label for="referenceId">Reference ID: </label>
|
||||||
<input
|
<input id="referenceId" :value="referenceId" placeholder="enter Reference ID here" @input="onInput" />
|
||||||
id="referenceId"
|
|
||||||
:value="referenceId"
|
|
||||||
placeholder="enter Reference ID here"
|
|
||||||
@input="onInput"
|
|
||||||
/>
|
|
||||||
<button @click="fetchData">Search Contacts</button>
|
<button @click="fetchData">Search Contacts</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Results</h2>
|
<h2>Results</h2>
|
||||||
<ContactsSummary v-if="contactData" :summary="contactData.data.summary" />
|
<ContactsSummary v-if="contactData" :summary="contactData.data.summary" />
|
||||||
<div v-else>No Contacts Found</div>
|
<div v-else>No Contacts Found</div>
|
||||||
<ContactTable
|
<ContactTable v-if="contactData" :table-data="contactData.data.findContactsCompletedBetween.edges" />
|
||||||
v-if="contactData"
|
|
||||||
:table-data="contactData.data.findContactsCompletedBetween.edges"
|
|
||||||
/>
|
|
||||||
<ErrorMessage v-if="errorMessage" :message="errorMessage" />
|
<ErrorMessage v-if="errorMessage" :message="errorMessage" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
95
src/views/SideBarView.vue
Normal file
95
src/views/SideBarView.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<script>
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
|
import { SidebarMenu } from "vue-sidebar-menu";
|
||||||
|
import "vue-sidebar-menu/dist/vue-sidebar-menu.css";
|
||||||
|
import { h, markRaw } from "vue";
|
||||||
|
|
||||||
|
const separator = {
|
||||||
|
template: '<hr style="border-color: rgba(0, 0, 0, 0.1); margin: 20px;">',
|
||||||
|
}
|
||||||
|
|
||||||
|
const faIcon = (props) => {
|
||||||
|
return {
|
||||||
|
element: markRaw({
|
||||||
|
render: () => h("div", [h(FontAwesomeIcon, { size: "lg", ...props })]),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SideBarView",
|
||||||
|
components: {
|
||||||
|
SidebarMenu,
|
||||||
|
},
|
||||||
|
|
||||||
|
// props: {
|
||||||
|
// sidebar: {
|
||||||
|
// type: Boolean,
|
||||||
|
// required: false
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
menu: [
|
||||||
|
{
|
||||||
|
header: "Services",
|
||||||
|
hiddenOnCollapse: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/",
|
||||||
|
title: "Home",
|
||||||
|
icon: faIcon({ icon: "fa-solid fa-house" }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/about",
|
||||||
|
title: "About",
|
||||||
|
icon: faIcon({ icon: "fa-solid fa-question" }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: markRaw(separator),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/referenceId",
|
||||||
|
title: "Contacts Lookup",
|
||||||
|
icon: faIcon({ icon: "fa-solid fa-rectangle-list" }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/interactionsFlow",
|
||||||
|
title: "Interactions Flow",
|
||||||
|
icon: faIcon({ icon: "fa-solid fa-route" }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/customerAccount/12345",
|
||||||
|
title: "Customer Account Example",
|
||||||
|
icon: faIcon({ icon: "fa-solid fa-id-card" }),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
collapsed: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.onResize();
|
||||||
|
window.addEventListener("resize", this.onResize);
|
||||||
|
console.log()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onResize() {
|
||||||
|
if (window.innerWidth <= 767) {
|
||||||
|
this.isOnMobile = true;
|
||||||
|
this.collapsed = true;
|
||||||
|
} else {
|
||||||
|
this.isOnMobile = false;
|
||||||
|
this.collapsed = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div v-if="this.$route.query.sidebar" id="sidebar">
|
||||||
|
<sidebar-menu v-model:collapsed="collapsed" :menu="menu" :show-one-child="true" :relative="true"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@ -1,12 +1,79 @@
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import vue from "@vitejs/plugin-vue";
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
import { createHtmlPlugin } from "vite-plugin-html";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig(({ command }) => {
|
||||||
plugins: [vue()],
|
if (command === "serve") {
|
||||||
resolve: {
|
return {
|
||||||
alias: {
|
// dev specific config
|
||||||
'vue': 'vue/dist/vue.esm-bundler',
|
plugins: [
|
||||||
},
|
vue(),
|
||||||
|
createHtmlPlugin({
|
||||||
|
minify: true,
|
||||||
|
/**
|
||||||
|
* After writing entry here, you will not need to add script tags in `index.html`, the original tags need to be deleted
|
||||||
|
* @default src/main.ts
|
||||||
|
*/
|
||||||
|
entry: "src/main.js",
|
||||||
|
/**
|
||||||
|
* If you want to store `index.html` in the specified folder, you can modify it, otherwise no configuration is required
|
||||||
|
* @default index.html
|
||||||
|
*/
|
||||||
|
template: "index.html",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that needs to be injected into the index.html ejs template
|
||||||
|
*/
|
||||||
|
inject: {
|
||||||
|
data: {
|
||||||
|
baseHref: '<base href="/"/>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
base: "/",
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
vue: "vue/dist/vue.esm-bundler",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// command === 'build'
|
||||||
|
return {
|
||||||
|
// build specific config
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
createHtmlPlugin({
|
||||||
|
minify: true,
|
||||||
|
/**
|
||||||
|
* After writing entry here, you will not need to add script tags in `index.html`, the original tags need to be deleted
|
||||||
|
* @default src/main.ts
|
||||||
|
*/
|
||||||
|
entry: "src/main.js",
|
||||||
|
/**
|
||||||
|
* If you want to store `index.html` in the specified folder, you can modify it, otherwise no configuration is required
|
||||||
|
* @default index.html
|
||||||
|
*/
|
||||||
|
template: "index.html",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that needs to be injected into the index.html ejs template
|
||||||
|
*/
|
||||||
|
inject: {
|
||||||
|
data: {
|
||||||
|
baseHref: '<base href="/eo-services/"/>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
base: "/eo-services/",
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
vue: "vue/dist/vue.esm-bundler",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user