PMCORE-2521
This commit is contained in:
10
package-lock.json
generated
10
package-lock.json
generated
@@ -10897,11 +10897,6 @@
|
||||
"vue": "^2.5.21"
|
||||
}
|
||||
},
|
||||
"vue-slim-tabs": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-slim-tabs/-/vue-slim-tabs-0.4.0.tgz",
|
||||
"integrity": "sha512-19bwuKs2HICja0E039QmE7N7PMQcjdZXcpigmXlJTtTYGZy40C112tZF6q7bS18XNZGFcd/sP3jOJRGC80gVVw=="
|
||||
},
|
||||
"vue-split-panel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-split-panel/-/vue-split-panel-1.0.4.tgz",
|
||||
@@ -10934,6 +10929,11 @@
|
||||
"vue-pagination-2": "^3.0"
|
||||
}
|
||||
},
|
||||
"vue-tabs-component": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz",
|
||||
"integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg=="
|
||||
},
|
||||
"vue-template-compiler": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
"vue-router": "^3.4.9",
|
||||
"vue-search-select": "^2.7.0",
|
||||
"vue-sidebar-menu": "^4.5.1",
|
||||
"vue-slim-tabs": "^0.4.0",
|
||||
"vue-split-panel": "^1.0.4",
|
||||
"vue-tables-2": "^2.1.46",
|
||||
"vue-upload-component": "^2.8.20",
|
||||
@@ -62,4 +61,4 @@
|
||||
"vuetify": "^1.1.4",
|
||||
"web-animations-js": "^2.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,14 @@ export let cases = {
|
||||
keys: {}
|
||||
});
|
||||
},
|
||||
summary(data) {
|
||||
return Api.get({
|
||||
service: "UNASSIGNED_LIST",
|
||||
params: {
|
||||
},
|
||||
keys: {}
|
||||
});
|
||||
},
|
||||
inputdocuments(data) {
|
||||
var params = new FormData();
|
||||
params.append('appUid', data.APP_UID);
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<Tabs>
|
||||
<Tab
|
||||
v-for="item in data.items"
|
||||
:key="item.title"
|
||||
:title="item.title"
|
||||
v-on:click="selectedTab"
|
||||
>
|
||||
{{ item.title }}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Tabs, Tab } from "vue-slim-tabs";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
data: Object,
|
||||
},
|
||||
components: {
|
||||
Tabs,
|
||||
Tab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
0: function () {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectedTab(e, index) {
|
||||
if (index === 0) {
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style src="vue-slim-tabs/themes/default.css"></style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div class="card v-pmase-summary-card">
|
||||
<div class="card-body">
|
||||
<div
|
||||
v-for="section in data"
|
||||
:key="section.title"
|
||||
class="v-attached-block"
|
||||
>
|
||||
<h6 class="card-subtitle mb-2 text-muted">{{ section.title }}</h6>
|
||||
<div class="card-text v-pmcase-summary-card-body">
|
||||
<div
|
||||
v-for="item in section.items"
|
||||
:key="item.title"
|
||||
class="v-attached-block"
|
||||
>
|
||||
<span> {{ item.label }} </span>:<span class="font-weight-bold">
|
||||
{{ item.value }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CaseSummary",
|
||||
props: {
|
||||
data: Object,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
classBtn(cls) {
|
||||
return "btn v-btn-request " + cls;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.v-pmcase-summary-card {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.v-pmcase-summary-card-body {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.v-pmcase-summary-center {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,40 +0,0 @@
|
||||
<template>
|
||||
<Tabs>
|
||||
<Tab
|
||||
v-for="item in data.items"
|
||||
:key="item.title"
|
||||
:title="item.title"
|
||||
v-on:click="selectedTab"
|
||||
>
|
||||
{{ item.title }}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Tabs, Tab } from "vue-slim-tabs";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
data: Object,
|
||||
},
|
||||
components: {
|
||||
Tabs,
|
||||
Tab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
0: function () {
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectedTab(e, index) {
|
||||
if (index === 0) {
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style src="vue-slim-tabs/themes/default.css"></style>
|
||||
41
resources/assets/js/components/tabs/Tab.vue
Normal file
41
resources/assets/js/components/tabs/Tab.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<section
|
||||
v-show="isActive"
|
||||
:aria-hidden="!isActive"
|
||||
class="tabs-component-panel"
|
||||
:id="computedId"
|
||||
role="tabpanel"
|
||||
>
|
||||
<slot />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
id: { default: null },
|
||||
name: { required: true },
|
||||
prefix: { default: "" },
|
||||
suffix: { default: "" },
|
||||
isDisabled: { default: false },
|
||||
},
|
||||
data: () => ({
|
||||
isActive: false,
|
||||
isVisible: true,
|
||||
}),
|
||||
computed: {
|
||||
header() {
|
||||
return this.prefix + this.name + this.suffix;
|
||||
},
|
||||
computedId() {
|
||||
return this.id ? this.id : this.name.toLowerCase().replace(/ /g, "-");
|
||||
},
|
||||
hash() {
|
||||
if (this.isDisabled) {
|
||||
return "#";
|
||||
}
|
||||
return "#" + this.computedId;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
160
resources/assets/js/components/tabs/Tabs.vue
Normal file
160
resources/assets/js/components/tabs/Tabs.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="tabs-component">
|
||||
<ul role="tablist" class="tabs-component-tabs">
|
||||
<li
|
||||
v-for="(tab, i) in tabs"
|
||||
:key="i"
|
||||
:class="{ 'is-active': tab.isActive, 'is-disabled': tab.isDisabled }"
|
||||
class="tabs-component-tab"
|
||||
role="presentation"
|
||||
v-show="tab.isVisible"
|
||||
>
|
||||
<span
|
||||
v-html="tab.header"
|
||||
:aria-controls="tab.hash"
|
||||
:aria-selected="tab.isActive"
|
||||
@click="selectTab(tab.hash, $event)"
|
||||
class="tabs-component-tab-a"
|
||||
role="tab"
|
||||
></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tabs-component-panels">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import expiringStorage from "./expiringStorage";
|
||||
export default {
|
||||
props: {
|
||||
cacheLifetime: {
|
||||
default: 5,
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({
|
||||
useUrlFragment: true,
|
||||
defaultTabHash: null,
|
||||
}),
|
||||
},
|
||||
},
|
||||
data: () => ({
|
||||
tabs: [],
|
||||
activeTabHash: "",
|
||||
activeTabIndex: 0,
|
||||
lastActiveTabHash: "",
|
||||
}),
|
||||
computed: {
|
||||
storageKey() {
|
||||
return `vue-tabs-component.cache.${window.location.host}${window.location.pathname}`;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.tabs = this.$children;
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener("hashchange", () =>
|
||||
this.selectTab(window.location.hash)
|
||||
);
|
||||
if (this.findTab(window.location.hash)) {
|
||||
this.selectTab(window.location.hash);
|
||||
return;
|
||||
}
|
||||
const previousSelectedTabHash = expiringStorage.get(this.storageKey);
|
||||
if (this.findTab(previousSelectedTabHash)) {
|
||||
this.selectTab(previousSelectedTabHash);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.options.defaultTabHash !== null &&
|
||||
this.findTab("#" + this.options.defaultTabHash)
|
||||
) {
|
||||
this.selectTab("#" + this.options.defaultTabHash);
|
||||
return;
|
||||
}
|
||||
if (this.tabs.length) {
|
||||
this.selectTab(this.tabs[0].hash);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
findTab(hash) {
|
||||
return this.tabs.find((tab) => tab.hash === hash);
|
||||
},
|
||||
selectTab(selectedTabHash, event) {
|
||||
// See if we should store the hash in the url fragment.
|
||||
if (event && !this.options.useUrlFragment) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const selectedTab = this.findTab(selectedTabHash);
|
||||
if (!selectedTab) {
|
||||
return;
|
||||
}
|
||||
if (selectedTab.isDisabled) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (this.lastActiveTabHash === selectedTab.hash) {
|
||||
this.$emit("clicked", { tab: selectedTab });
|
||||
return;
|
||||
}
|
||||
this.tabs.forEach((tab) => {
|
||||
tab.isActive = tab.hash === selectedTab.hash;
|
||||
});
|
||||
this.$emit("changed", { tab: selectedTab });
|
||||
this.activeTabHash = selectedTab.hash;
|
||||
this.activeTabIndex = this.getTabIndex(selectedTabHash);
|
||||
this.lastActiveTabHash = this.activeTabHash = selectedTab.hash;
|
||||
expiringStorage.set(
|
||||
this.storageKey,
|
||||
selectedTab.hash,
|
||||
this.cacheLifetime
|
||||
);
|
||||
},
|
||||
setTabVisible(hash, visible) {
|
||||
const tab = this.findTab(hash);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
tab.isVisible = visible;
|
||||
if (tab.isActive) {
|
||||
// If tab is active, set a different one as active.
|
||||
tab.isActive = visible;
|
||||
this.tabs.every((tab, index, array) => {
|
||||
if (tab.isVisible) {
|
||||
tab.isActive = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getTabIndex(hash) {
|
||||
const tab = this.findTab(hash);
|
||||
|
||||
return this.tabs.indexOf(tab);
|
||||
},
|
||||
|
||||
getTabHash(index) {
|
||||
const tab = this.tabs.find((tab) => this.tabs.indexOf(tab) === index);
|
||||
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
return tab.hash;
|
||||
},
|
||||
|
||||
getActiveTab() {
|
||||
return this.findTab(this.activeTabHash);
|
||||
},
|
||||
|
||||
getActiveTabIndex() {
|
||||
return this.getTabIndex(this.activeTabHash);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
30
resources/assets/js/components/tabs/expiringStorage.js
Normal file
30
resources/assets/js/components/tabs/expiringStorage.js
Normal file
@@ -0,0 +1,30 @@
|
||||
class ExpiringStorage {
|
||||
get(key) {
|
||||
const cached = JSON.parse(
|
||||
localStorage.getItem(key)
|
||||
);
|
||||
|
||||
if (!cached) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const expires = new Date(cached.expires);
|
||||
|
||||
if (expires < new Date()) {
|
||||
localStorage.removeItem(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return cached.value;
|
||||
}
|
||||
|
||||
set(key, value, lifeTimeInMinutes) {
|
||||
const currentTime = new Date().getTime();
|
||||
|
||||
const expires = new Date(currentTime + lifeTimeInMinutes * 60000);
|
||||
|
||||
localStorage.setItem(key, JSON.stringify({ value, expires }));
|
||||
}
|
||||
}
|
||||
|
||||
export default new ExpiringStorage();
|
||||
@@ -40,7 +40,7 @@
|
||||
</div>
|
||||
</v-server-table>
|
||||
</div>
|
||||
<Tabs :data="dataTabs"></Tabs>
|
||||
<TabsCaseDetail :dataCaseSummary="dataCaseSummaryTab"></TabsCaseDetail>
|
||||
</div>
|
||||
<div class="col-sm4">
|
||||
<case-summary
|
||||
@@ -73,19 +73,18 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tabs from "../components/home/caseDetail/Tabs.vue";
|
||||
import IoDocuments from "../components/home/caseDetail/IoDocuments.vue";
|
||||
import CaseSummary from "../components/home/caseDetail/CaseSummary.vue";
|
||||
import AttachedDocuments from "../components/home/caseDetail/AttachedDocuments.vue";
|
||||
import CaseComment from "../components/home/caseDetail/CaseComment";
|
||||
import CaseComments from "../components/home/caseDetail/CaseComments";
|
||||
import TabsCaseDetail from "../home/TabsCaseDetail.vue";
|
||||
|
||||
import Api from "../api/index";
|
||||
|
||||
export default {
|
||||
name: "CaseDetail",
|
||||
components: {
|
||||
Tabs,
|
||||
TabsCaseDetail,
|
||||
IoDocuments,
|
||||
CaseSummary,
|
||||
AttachedDocuments,
|
||||
@@ -133,6 +132,7 @@ export default {
|
||||
filterable: false,
|
||||
},
|
||||
dataCaseSummary: null,
|
||||
dataCaseSummaryTab: null,
|
||||
dataIoDocuments: {
|
||||
titleInput: this.$i18n.t("ID_REQUEST_DOCUMENTS"),
|
||||
titleOutput: this.$i18n.t("ID_OUTPUT_DOCUMENTS"),
|
||||
@@ -143,32 +143,6 @@ export default {
|
||||
title: "Attached Documents",
|
||||
items: [],
|
||||
},
|
||||
dataTabs: {
|
||||
items: [
|
||||
{
|
||||
title: "Request Summary",
|
||||
data: {
|
||||
firstName: "Jason",
|
||||
lastName: "Burne",
|
||||
userName: "jburne@processmaker.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Process Map",
|
||||
data: [
|
||||
{
|
||||
pro_uid: "123dit",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Case History",
|
||||
},
|
||||
{
|
||||
title: "Change Log",
|
||||
},
|
||||
],
|
||||
},
|
||||
dataComments: {
|
||||
title: "Comments",
|
||||
items: [],
|
||||
@@ -215,10 +189,12 @@ export default {
|
||||
this.dataAttachedDocuments.items = att;
|
||||
},
|
||||
getDataCaseSummary() {
|
||||
let that = this;
|
||||
Api.cases
|
||||
.casesummary(this.dataCase)
|
||||
.then((response) => {
|
||||
var data = response.data;
|
||||
this.formatCaseSummary(response.data);
|
||||
this.dataCaseSummary = {
|
||||
title: "Case Summary",
|
||||
titleActions: "Actions",
|
||||
@@ -361,6 +337,27 @@ export default {
|
||||
|
||||
this.dataComments.items = notesArray;
|
||||
},
|
||||
formatCaseSummary(data) {
|
||||
let index,
|
||||
sections = [];
|
||||
this.dataCaseSummaryTab = [];
|
||||
_.each(data, (o) => {
|
||||
if (
|
||||
(index = _.findIndex(sections, (s) => {
|
||||
return s.title == o.section;
|
||||
})) == -1
|
||||
) {
|
||||
sections.push({
|
||||
title: o.section,
|
||||
items: [],
|
||||
});
|
||||
index = 0;
|
||||
}
|
||||
sections[index].items.push(o);
|
||||
});
|
||||
|
||||
this.dataCaseSummaryTab = sections;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
152
resources/assets/js/home/TabsCaseDetail.vue
Normal file
152
resources/assets/js/home/TabsCaseDetail.vue
Normal file
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div>
|
||||
<tabs>
|
||||
<tab :name="$t('ID_SUMMARY')">
|
||||
<PmCaseSummary :data="dataCaseSummary"> </PmCaseSummary>
|
||||
</tab>
|
||||
<tab name="Second tab">
|
||||
<h2 class="page-subtitle">Second tab</h2>
|
||||
This is the content of the second tab.
|
||||
</tab>
|
||||
<tab name="Disabled tab" :is-disabled="true">
|
||||
<h2 class="page-subtitle">Disabled tab</h2>
|
||||
This content will be unavailable while :is-disabled prop set to true
|
||||
</tab>
|
||||
<tab id="oh-hi-mark" name="Custom fragment">
|
||||
<h2 class="page-subtitle">Custom fragment</h2>
|
||||
The hash that is appended to the url can be customized.
|
||||
</tab>
|
||||
<tab
|
||||
prefix="<span class='prefix'>→</span>"
|
||||
name="Prefix and suffix"
|
||||
suffix="<span class='suffix'>4</span>"
|
||||
>
|
||||
<h2 class="page-subtitle">Prefix and suffix</h2>
|
||||
A prefix and a suffix can be added — HTML allowed.
|
||||
</tab>
|
||||
</tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tabs from "./../components/tabs/Tabs.vue";
|
||||
import Tab from "./../components/tabs/Tab.vue";
|
||||
import PmCaseSummary from "./../components/home/caseDetail/PmCaseSummary.vue";
|
||||
import Api from "../api/index";
|
||||
|
||||
export default {
|
||||
name: "TabsCaseDetail",
|
||||
components: {
|
||||
Tabs,
|
||||
Tab,
|
||||
PmCaseSummary,
|
||||
},
|
||||
props: {
|
||||
dataCaseSummary: Array,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.tabs-component {
|
||||
margin: 0 0;
|
||||
}
|
||||
|
||||
.tabs-component-tabs {
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
.tabs-component-tabs {
|
||||
border: 0;
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs-component-tab {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-right: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.tabs-component-tab:not(:last-child) {
|
||||
border-bottom: dotted 1px #ddd;
|
||||
}
|
||||
|
||||
.tabs-component-tab:hover {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tabs-component-tab.is-active {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.tabs-component-tab.is-disabled * {
|
||||
color: #cdcdcd;
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
.tabs-component-tab {
|
||||
background-color: #fff;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 3px 3px 0 0;
|
||||
margin-right: 0.5em;
|
||||
transform: translateY(2px);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tabs-component-tab.is-active {
|
||||
border-bottom: solid 1px #fff;
|
||||
z-index: 2;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.tabs-component-tab-a {
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
display: flex;
|
||||
padding: 0.75em 1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tabs-component-panels {
|
||||
padding: 4em 0;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
.tabs-component-panels {
|
||||
border-top-left-radius: 0;
|
||||
background-color: #fff;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
|
||||
padding: 0.5em 0.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user