TimeTrex Community Edition v16.2.0
This commit is contained in:
30
interface/html5/framework/apollo-vue/src/pages/Access.vue
Normal file
30
interface/html5/framework/apollo-vue/src/pages/Access.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="exception-body access-body">
|
||||
<div class="exception-container">
|
||||
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
|
||||
<h1>Denied</h1>
|
||||
<p>
|
||||
You do not have the necessary privileges.
|
||||
</p>
|
||||
<router-link to="/">
|
||||
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
logoColor() {
|
||||
if (this.$appState.colorScheme === 'light')
|
||||
return 'dark';
|
||||
else return 'white';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
118
interface/html5/framework/apollo-vue/src/pages/CalendarDemo.vue
Normal file
118
interface/html5/framework/apollo-vue/src/pages/CalendarDemo.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="p-grid">
|
||||
<div class="p-col-12">
|
||||
<div class="card">
|
||||
<FullCalendar :events="events" :options="options" />
|
||||
|
||||
<Dialog v-model:visible="eventDialog" :style="{width: '450px'}" header="Event Details" :modal="true" :closable="true">
|
||||
<div class="p-fluid">
|
||||
<div class="p-field">
|
||||
<label for="title">Title</label>
|
||||
<InputText id="title" v-if="clickedEvent" v-model="changedEvent.title" required="true" autofocus/>
|
||||
</div>
|
||||
<div class="p-field">
|
||||
<label for="start">From</label>
|
||||
<Calendar id="start" v-if="clickedEvent" v-model="changedEvent.start" :showTime="true" appendTo="body"/>
|
||||
</div>
|
||||
<div class="p-field">
|
||||
<label for="end">To</label>
|
||||
<Calendar id="end" v-if="clickedEvent" v-model="changedEvent.end" :showTime="true" appendTo="body"/>
|
||||
</div>
|
||||
<div class="p-field-checkbox">
|
||||
<Checkbox id="allday" name="allday" value="All Day" v-model="changedEvent.allDay" />
|
||||
<label for="allday">All Day</label>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="save"/>
|
||||
<Button label="Reset" icon="pi pi-refresh" class="p-button-text" @click="reset" />
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EventService from '../service/EventService';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import interactionPlugin from '@fullcalendar/interaction';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
eventDialog: false,
|
||||
clickedEvent: null,
|
||||
changedEvent: {title:'', start: null, end:'', allDay: null},
|
||||
options: {
|
||||
plugins:[dayGridPlugin, timeGridPlugin, interactionPlugin],
|
||||
initialDate : '2023-01-01',
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
||||
},
|
||||
editable: true,
|
||||
selectable:true,
|
||||
selectMirror: true,
|
||||
dayMaxEvents: true,
|
||||
eventClick: (e) => {
|
||||
this.eventDialog = true;
|
||||
|
||||
this.clickedEvent = e.event;
|
||||
|
||||
this.changedEvent.title = this.clickedEvent.title;
|
||||
this.changedEvent.start = this.clickedEvent.start;
|
||||
this.changedEvent.end = this.clickedEvent.end;
|
||||
}
|
||||
},
|
||||
events: null
|
||||
};
|
||||
},
|
||||
eventService: null,
|
||||
created() {
|
||||
this.eventService = new EventService();
|
||||
},
|
||||
mounted() {
|
||||
this.eventService.getEvents().then(data => this.events = data);
|
||||
},
|
||||
methods: {
|
||||
findIndexById(id) {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.events.length; i++) {
|
||||
if (this.events[i].id === id) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
},
|
||||
save() {
|
||||
this.eventDialog = false;
|
||||
|
||||
this.clickedEvent.setProp('title', this.changedEvent.title)
|
||||
this.clickedEvent.setStart(this.changedEvent.start)
|
||||
this.clickedEvent.setEnd(this.changedEvent.end)
|
||||
this.clickedEvent.setAllDay(this.changedEvent.allDay)
|
||||
|
||||
this.changedEvent = {title:'', start: null, end:'', allDay: null};
|
||||
},
|
||||
reset() {
|
||||
this.changedEvent.title = this.clickedEvent.title;
|
||||
this.changedEvent.start = this.clickedEvent.start;
|
||||
this.changedEvent.end = this.clickedEvent.end;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@media screen and (max-width: 960px) {
|
||||
::v-deep(.fc-header-toolbar) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
</style>
|
350
interface/html5/framework/apollo-vue/src/pages/CrudDemo.vue
Normal file
350
interface/html5/framework/apollo-vue/src/pages/CrudDemo.vue
Normal file
@@ -0,0 +1,350 @@
|
||||
<template>
|
||||
<div class="p-grid crud-demo">
|
||||
<div class="p-col-12">
|
||||
<div class="card">
|
||||
<Toast/>
|
||||
<Toolbar class="p-mb-4">
|
||||
<template v-slot:left>
|
||||
<Button label="New" icon="pi pi-plus" class="p-button-success p-mr-2" @click="openNew" />
|
||||
<Button label="Delete" icon="pi pi-trash" class="p-button-danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" />
|
||||
</template>
|
||||
|
||||
<template v-slot:right>
|
||||
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="p-mr-2 p-d-inline-block" />
|
||||
<Button label="Export" icon="pi pi-upload" class="p-button-help" @click="exportCSV($event)" />
|
||||
</template>
|
||||
</Toolbar>
|
||||
|
||||
<DataTable ref="dt" :value="products" v-model:selection="selectedProducts" dataKey="id" :paginator="true" :rows="10" :filters="filters"
|
||||
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[5,10,25]"
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products" responsiveLayout="scroll">
|
||||
<template #header>
|
||||
<div class="table-header p-d-flex p-flex-column p-flex-md-row p-jc-md-between p-ai-start p-ai-md-center">
|
||||
<h5 class="p-mb-2 p-m-md-0">Manage Products</h5>
|
||||
<span class="p-input-icon-left">
|
||||
<i class="pi pi-search" />
|
||||
<InputText v-model="filters['global'].value" placeholder="Search..." />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Column selectionMode="multiple" headerStyle="width: 3rem"></Column>
|
||||
<Column field="code" header="Code" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Code</span>
|
||||
{{slotProps.data.code}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="name" header="Name" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Name</span>
|
||||
{{slotProps.data.name}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="Image">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Image</span>
|
||||
<img :src="'assets/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" class="product-image" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="price" header="Price" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Price</span>
|
||||
{{formatCurrency(slotProps.data.price)}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="category" header="Category" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Category</span>
|
||||
{{formatCurrency(slotProps.data.category)}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="rating" header="Reviews" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Rating</span>
|
||||
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="inventoryStatus" header="Status" :sortable="true">
|
||||
<template #body="slotProps">
|
||||
<span class="p-column-title">Status</span>
|
||||
<span :class="'product-badge status-' + (slotProps.data.inventoryStatus ? slotProps.data.inventoryStatus.toLowerCase() : '')">{{slotProps.data.inventoryStatus}}</span>
|
||||
</template>
|
||||
</Column>
|
||||
<Column>
|
||||
<template #body="slotProps">
|
||||
<Button icon="pi pi-pencil" class="p-button-rounded p-button-success p-mr-2" @click="editProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-trash" class="p-button-rounded p-button-warning" @click="confirmDeleteProduct(slotProps.data)" />
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
|
||||
<Dialog v-model:visible="productDialog" :style="{width: '450px'}" header="Product Details" :modal="true" class="p-fluid">
|
||||
<img :src="'assets/demo/images/product/' + product.image" :alt="product.image" class="product-image" v-if="product.image" />
|
||||
<div class="p-field">
|
||||
<label for="name">Name</label>
|
||||
<InputText id="name" v-model.trim="product.name" required="true" autofocus :class="{'p-invalid': submitted && !product.name}" />
|
||||
<small class="p-invalid" v-if="submitted && !product.name">Name is required.</small>
|
||||
</div>
|
||||
<div class="p-field">
|
||||
<label for="description">Description</label>
|
||||
<Textarea id="description" v-model="product.description" required="true" rows="3" cols="20" />
|
||||
</div>
|
||||
|
||||
<div class="p-field">
|
||||
<label for="inventoryStatus" class="p-mb-3">Inventory Status</label>
|
||||
<Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status">
|
||||
<template #value="slotProps">
|
||||
<div v-if="slotProps.value && slotProps.value.value">
|
||||
<span :class="'product-badge status-' +slotProps.value.value">{{slotProps.value.label}}</span>
|
||||
</div>
|
||||
<div v-else-if="slotProps.value && !slotProps.value.value">
|
||||
<span :class="'product-badge status-' +slotProps.value.toLowerCase()">{{slotProps.value}}</span>
|
||||
</div>
|
||||
<span v-else>
|
||||
{{slotProps.placeholder}}
|
||||
</span>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
<div class="p-field">
|
||||
<label class="p-mb-3">Category</label>
|
||||
<div class="p-formgrid p-grid">
|
||||
<div class="p-field-radiobutton p-col-6">
|
||||
<RadioButton id="category1" name="category" value="Accessories" v-model="product.category" />
|
||||
<label for="category1">Accessories</label>
|
||||
</div>
|
||||
<div class="p-field-radiobutton p-col-6">
|
||||
<RadioButton id="category2" name="category" value="Clothing" v-model="product.category" />
|
||||
<label for="category2">Clothing</label>
|
||||
</div>
|
||||
<div class="p-field-radiobutton p-col-6">
|
||||
<RadioButton id="category3" name="category" value="Electronics" v-model="product.category" />
|
||||
<label for="category3">Electronics</label>
|
||||
</div>
|
||||
<div class="p-field-radiobutton p-col-6">
|
||||
<RadioButton id="category4" name="category" value="Fitness" v-model="product.category" />
|
||||
<label for="category4">Fitness</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-formgrid p-grid">
|
||||
<div class="p-field p-col">
|
||||
<label for="price">Price</label>
|
||||
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" />
|
||||
</div>
|
||||
<div class="p-field p-col">
|
||||
<label for="quantity">Quantity</label>
|
||||
<InputNumber id="quantity" v-model="product.quantity" integeronly />
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/>
|
||||
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveProduct" />
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:visible="deleteProductDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
|
||||
<div class="confirmation-content">
|
||||
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
|
||||
<span v-if="product">Are you sure you want to delete <b>{{product.name}}</b>?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductDialog = false"/>
|
||||
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteProduct" />
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:visible="deleteProductsDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
|
||||
<div class="confirmation-content">
|
||||
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
|
||||
<span v-if="product">Are you sure you want to delete the selected products?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductsDialog = false"/>
|
||||
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteSelectedProducts" />
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {FilterMatchMode} from 'primevue/api';
|
||||
import ProductService from '../service/ProductService';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
products: null,
|
||||
productDialog: false,
|
||||
deleteProductDialog: false,
|
||||
deleteProductsDialog: false,
|
||||
product: {},
|
||||
selectedProducts: null,
|
||||
filters: {},
|
||||
submitted: false,
|
||||
statuses: [
|
||||
{label: 'INSTOCK', value: 'instock'},
|
||||
{label: 'LOWSTOCK', value: 'lowstock'},
|
||||
{label: 'OUTOFSTOCK', value: 'outofstock'}
|
||||
]
|
||||
}
|
||||
},
|
||||
productService: null,
|
||||
created() {
|
||||
this.productService = new ProductService();
|
||||
this.initFilters();
|
||||
},
|
||||
mounted() {
|
||||
this.productService.getProducts().then(data => this.products = data);
|
||||
},
|
||||
methods: {
|
||||
formatCurrency(value) {
|
||||
if(value)
|
||||
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
|
||||
return;
|
||||
},
|
||||
openNew() {
|
||||
this.product = {};
|
||||
this.submitted = false;
|
||||
this.productDialog = true;
|
||||
},
|
||||
hideDialog() {
|
||||
this.productDialog = false;
|
||||
this.submitted = false;
|
||||
},
|
||||
saveProduct() {
|
||||
this.submitted = true;
|
||||
if (this.product.name.trim()) {
|
||||
if (this.product.id) {
|
||||
this.product.inventoryStatus = this.product.inventoryStatus.value ? this.product.inventoryStatus.value: this.product.inventoryStatus;
|
||||
this.products[this.findIndexById(this.product.id)] = this.product;
|
||||
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Updated', life: 3000});
|
||||
}
|
||||
else {
|
||||
this.product.id = this.createId();
|
||||
this.product.code = this.createId();
|
||||
this.product.image = 'product-placeholder.svg';
|
||||
this.product.inventoryStatus = this.product.inventoryStatus ? this.product.inventoryStatus.value : 'INSTOCK';
|
||||
this.products.push(this.product);
|
||||
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Created', life: 3000});
|
||||
}
|
||||
this.productDialog = false;
|
||||
this.product = {};
|
||||
}
|
||||
},
|
||||
editProduct(product) {
|
||||
this.product = {...product};
|
||||
this.productDialog = true;
|
||||
},
|
||||
confirmDeleteProduct(product) {
|
||||
this.product = product;
|
||||
this.deleteProductDialog = true;
|
||||
},
|
||||
deleteProduct() {
|
||||
this.products = this.products.filter(val => val.id !== this.product.id);
|
||||
this.deleteProductDialog = false;
|
||||
this.product = {};
|
||||
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Deleted', life: 3000});
|
||||
},
|
||||
findIndexById(id) {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.products.length; i++) {
|
||||
if (this.products[i].id === id) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
},
|
||||
createId() {
|
||||
let id = '';
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for ( var i = 0; i < 5; i++ ) {
|
||||
id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return id;
|
||||
},
|
||||
exportCSV() {
|
||||
this.$refs.dt.exportCSV();
|
||||
},
|
||||
confirmDeleteSelected() {
|
||||
this.deleteProductsDialog = true;
|
||||
},
|
||||
deleteSelectedProducts() {
|
||||
this.products = this.products.filter(val => !this.selectedProducts.includes(val));
|
||||
this.deleteProductsDialog = false;
|
||||
this.selectedProducts = null;
|
||||
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000});
|
||||
},
|
||||
initFilters() {
|
||||
this.filters = {
|
||||
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100px;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
|
||||
}
|
||||
|
||||
.p-dialog .product-image {
|
||||
width: 150px;
|
||||
margin: 0 auto 2rem auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.confirmation-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.product-badge {
|
||||
border-radius: 2px;
|
||||
padding: .25em .5rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
letter-spacing: .3px;
|
||||
|
||||
&.status-instock {
|
||||
background: #C8E6C9;
|
||||
color: #256029;
|
||||
}
|
||||
|
||||
&.status-outofstock {
|
||||
background: #FFCDD2;
|
||||
color: #C63737;
|
||||
}
|
||||
|
||||
&.status-lowstock {
|
||||
background: #FEEDAF;
|
||||
color: #8A5340;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
::v-deep(.p-toolbar) {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.p-button {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
31
interface/html5/framework/apollo-vue/src/pages/Error.vue
Normal file
31
interface/html5/framework/apollo-vue/src/pages/Error.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="exception-body error-body">
|
||||
<div class="exception-container">
|
||||
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
|
||||
<h1>Error</h1>
|
||||
<p>
|
||||
Please contact the system administrator.
|
||||
</p>
|
||||
|
||||
<router-link to="/">
|
||||
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
logoColor() {
|
||||
if (this.$appState.colorScheme === 'light')
|
||||
return 'dark';
|
||||
else return 'white';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
146
interface/html5/framework/apollo-vue/src/pages/Help.vue
Normal file
146
interface/html5/framework/apollo-vue/src/pages/Help.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="p-grid help-page">
|
||||
<div class="p-col-12">
|
||||
<div class="card help-search">
|
||||
<div class="help-search-content">
|
||||
<h1>We are here to help</h1>
|
||||
<div class="search-container">
|
||||
<i class="pi pi-search"></i>
|
||||
<InputText type="text" placeholder="Search" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-col-12 p-lg-6">
|
||||
<div class="card">
|
||||
<h4>General</h4>
|
||||
<Accordion :activeIndex="0">
|
||||
<AccordionTab header="Header I">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
|
||||
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</AccordionTab>
|
||||
<AccordionTab header="Header II">
|
||||
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
|
||||
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
|
||||
voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.</p>
|
||||
</AccordionTab>
|
||||
<AccordionTab header="Header III">
|
||||
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati
|
||||
cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio.
|
||||
Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.</p>
|
||||
</AccordionTab>
|
||||
</Accordion>
|
||||
|
||||
<h4>FAQ</h4>
|
||||
<Accordion :activeIndex="0">
|
||||
<AccordionTab header="FAQ I">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
|
||||
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</AccordionTab>
|
||||
<AccordionTab header="FAQ II">
|
||||
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
|
||||
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
|
||||
voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.</p>
|
||||
</AccordionTab>
|
||||
<AccordionTab header="FAQ III">
|
||||
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati
|
||||
cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio.
|
||||
Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.</p>
|
||||
</AccordionTab>
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="p-col-12 p-lg-6">
|
||||
<div class="card">
|
||||
<h4>System Status</h4>
|
||||
<p>All services are operational.</p>
|
||||
<div class="status-bars">
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar status-bar-failure"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="status-bar"></div>
|
||||
</div>
|
||||
<div class="status-bar-footer">
|
||||
<span>30 Days Ago</span>
|
||||
<span>Today</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h4>Articles</h4>
|
||||
<p>Recent articles from our team.</p>
|
||||
<div class="blog-posts">
|
||||
<div class="blog-post">
|
||||
<div class="blog-text">
|
||||
<h1>Building Revenue With Confidence</h1>
|
||||
<span>And avoiding failures</span>
|
||||
</div>
|
||||
<div class="blog-profile">
|
||||
<img src="assets/demo/images/avatar/amyelsner.png" alt="apollo" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="blog-post">
|
||||
<div class="blog-text">
|
||||
<h1>Latest Marketing Trends</h1>
|
||||
<span>Don't miss out our tips</span>
|
||||
</div>
|
||||
<div class="blog-profile">
|
||||
<img src="assets/demo/images/avatar/annafali.png" alt="apollo" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="blog-post">
|
||||
<div class="blog-text">
|
||||
<h1>How To Reach Your Audience</h1>
|
||||
<span>10 ways to increase your efficiency</span>
|
||||
</div>
|
||||
<div class="blog-profile">
|
||||
<img src="assets/demo/images/avatar/stephenshaw.png" alt="apollo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
117
interface/html5/framework/apollo-vue/src/pages/Invoice.vue
Normal file
117
interface/html5/framework/apollo-vue/src/pages/Invoice.vue
Normal file
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div>
|
||||
<Button label="Print" icon="pi pi-print" @click="printClick" style="display: block; margin-bottom: 20px; margin-left: 6px" :key="1"></Button>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col">
|
||||
<div class="card" >
|
||||
<div id="invoice-content">
|
||||
<div class="invoice">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-company">
|
||||
<img id="invoice-logo" class="logo-image" :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout" />
|
||||
<div class="company-name">YOUR COMPANY</div>
|
||||
<div>9137 3rd Lane California City</div>
|
||||
<div>CA 93504, U.S.A.</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="invoice-title">INVOICE</div>
|
||||
<div class="invoice-details">
|
||||
<div class="invoice-label">DATE</div>
|
||||
<div class="invoice-value">{{new Date().toISOString().split('T')[0]}}</div>
|
||||
|
||||
<div class="invoice-label">INVOICE #</div>
|
||||
<div class="invoice-value">8523</div>
|
||||
|
||||
<div class="invoice-label">CUSTOMER ID</div>
|
||||
<div class="invoice-value">C1613</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-to">
|
||||
<div class="bill-to">BILL TO</div>
|
||||
<div class="invoice-to-info">
|
||||
<div>Claire Williams, 148 Hope Lane</div>
|
||||
<div>Palo Alto, CA 94304. </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-items">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Quantity</th>
|
||||
<th>Unit Price</th>
|
||||
<th>Line Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Green T-Shirt</td>
|
||||
<td>1</td>
|
||||
<td>$49.00</td>
|
||||
<td>$49.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Game Controller</td>
|
||||
<td>2</td>
|
||||
<td>$99.00</td>
|
||||
<td>$198.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mini Speakers</td>
|
||||
<td>1</td>
|
||||
<td>$85.00</td>
|
||||
<td>$85.00</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="invoice-summary">
|
||||
<div class="invoice-notes">
|
||||
<b>NOTES</b>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="invoice-details">
|
||||
<div class="invoice-label">SUBTOTAL</div>
|
||||
<div class="invoice-value">$332.00</div>
|
||||
|
||||
<div class="invoice-label">VAT</div>
|
||||
<div class="invoice-value">0</div>
|
||||
|
||||
<div class="invoice-label">TOTAL</div>
|
||||
<div class="invoice-value">$332.00</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
printClick() {
|
||||
window.print();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
logoColor() {
|
||||
if (this.$appState.colorScheme === 'light')
|
||||
return 'dark';
|
||||
else return 'white';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
55
interface/html5/framework/apollo-vue/src/pages/Login.vue
Normal file
55
interface/html5/framework/apollo-vue/src/pages/Login.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="login-body">
|
||||
<div class="body-container">
|
||||
<div class="p-grid">
|
||||
<div class="p-col-12 p-lg-6 left-side">
|
||||
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
|
||||
<h1>Welcome</h1>
|
||||
<p>
|
||||
Sign in to start your session
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-col-12 p-lg-6 right-side">
|
||||
<div class="login-wrapper">
|
||||
<div class="login-container">
|
||||
<span class="title">Login</span>
|
||||
|
||||
<div class="p-grid p-fluid">
|
||||
<div class="p-col-12">
|
||||
<InputText placeholder="Username"/>
|
||||
</div>
|
||||
<div class="p-col-12">
|
||||
<InputText type="password" placeholder="Password"/>
|
||||
</div>
|
||||
<div class="p-col-6">
|
||||
<router-link to="/">
|
||||
<Button label="Sign In" icon="pi pi-check"/>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="p-col-6 password-container">
|
||||
<button class="p-link">Forgot Password?</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
logoColor() {
|
||||
if (this.$appState.colorScheme === 'light')
|
||||
return 'dark';
|
||||
else return 'white';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
31
interface/html5/framework/apollo-vue/src/pages/NotFound.vue
Normal file
31
interface/html5/framework/apollo-vue/src/pages/NotFound.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="exception-body notfound-body">
|
||||
<div class="exception-container">
|
||||
<img :src="'assets/layout/images/logo-' + logoColor + '.png'" alt="apollo-layout"/>
|
||||
<h1>Not Found</h1>
|
||||
<p>
|
||||
Resource is not found.
|
||||
</p>
|
||||
|
||||
<router-link to="/">
|
||||
<Button label="Go To Dashboard" icon="pi pi-arrow-left" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
logoColor() {
|
||||
if (this.$appState.colorScheme === 'light')
|
||||
return 'dark';
|
||||
else return 'white';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
126
interface/html5/framework/apollo-vue/src/pages/TimelineDemo.vue
Normal file
126
interface/html5/framework/apollo-vue/src/pages/TimelineDemo.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<div class="p-grid">
|
||||
<div class="p-col-12">
|
||||
<div class="card">
|
||||
<h4>Timeline</h4>
|
||||
|
||||
<h5>Custom Timeline</h5>
|
||||
<Timeline :value="customEvents" align="alternate" class="customized-timeline">
|
||||
<template #marker="slotProps">
|
||||
<span class="custom-marker p-shadow-2" :style="{backgroundColor: slotProps.item.color}">
|
||||
<i :class="slotProps.item.icon"></i>
|
||||
</span>
|
||||
</template>
|
||||
<template #content="slotProps">
|
||||
<Card>
|
||||
<template #title>
|
||||
{{slotProps.item.status}}
|
||||
</template>
|
||||
<template #subtitle>
|
||||
{{slotProps.item.date}}
|
||||
</template>
|
||||
<template #content>
|
||||
<img v-if="slotProps.item.image" :src="'assets/demo/images/product/' + slotProps.item.image" :alt="slotProps.item.name" width="200" class="p-shadow-2" />
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt
|
||||
quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!</p>
|
||||
<Button label="Read more" class="p-button-text"></Button>
|
||||
</template>
|
||||
</Card>
|
||||
</template>
|
||||
</Timeline>
|
||||
|
||||
<h5 style="margin-top: 5em">Horizontal - Alternate Align</h5>
|
||||
<Timeline :value="horizontalEvents" layout="horizontal" align="alternate">
|
||||
<template #content="slotProps">
|
||||
{{slotProps.item}}
|
||||
</template>
|
||||
<template #opposite>
|
||||
|
||||
</template>
|
||||
</Timeline>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
customEvents: [
|
||||
{
|
||||
status: 'Ordered',
|
||||
date: '15/10/2020 10:30',
|
||||
icon: 'pi pi-shopping-cart',
|
||||
color: '#9C27B0',
|
||||
image: 'game-controller.jpg'
|
||||
},
|
||||
{
|
||||
status: 'Processing',
|
||||
date: '15/10/2020 14:00',
|
||||
icon: 'pi pi-cog',
|
||||
color: '#673AB7'
|
||||
},
|
||||
{
|
||||
status: 'Shipped',
|
||||
date: '15/10/2020 16:15',
|
||||
icon: 'pi pi-envelope',
|
||||
color: '#FF9800'
|
||||
},
|
||||
{
|
||||
status: 'Delivered',
|
||||
date: '16/10/2020 10:00',
|
||||
icon: 'pi pi-check',
|
||||
color: '#607D8B'
|
||||
}
|
||||
],
|
||||
horizontalEvents: [
|
||||
'2020', '2021', '2022', '2023'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-marker {
|
||||
display: flex;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
::v-deep(.p-button) {
|
||||
min-width: 8em;
|
||||
}
|
||||
|
||||
::v-deep(.p-timeline-event-content) {
|
||||
line-height: 1;
|
||||
}
|
||||
::v-deep(.p-timeline-event-opposite) {
|
||||
line-height: 1;
|
||||
}
|
||||
@media screen and (max-width: 960px) {
|
||||
::v-deep(.customized-timeline) {
|
||||
.p-timeline-event:nth-child(even) {
|
||||
flex-direction: row !important;
|
||||
|
||||
.p-timeline-event-content {
|
||||
text-align: left !important;
|
||||
}
|
||||
}
|
||||
.p-timeline-event-opposite {
|
||||
flex: 0;
|
||||
}
|
||||
.p-card {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
Reference in New Issue
Block a user