Skip to content

Commit

Permalink
Merge pull request #1229 from slntopp/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
SazukinPavel authored Nov 13, 2023
2 parents 95318ef + 436c8f6 commit 96835d4
Show file tree
Hide file tree
Showing 17 changed files with 265 additions and 47 deletions.
16 changes: 14 additions & 2 deletions admin-ui/src/components/account/info.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
<template>
<v-card elevation="0" color="background-light" class="pa-4">
<div style="position: absolute; top: 0; right: 25px">
<div style="position: absolute; top: 0; right: 25px;max-width: 45%;">
<div>
<v-chip class="mr-3" color="primary" outlined
<v-chip class="ma-1" color="primary" outlined
>Balance: {{ account.balance?.toFixed(2) || 0 }}
{{ account.currency }}</v-chip
>
<v-btn
class="ma-1"
:to="{
name: 'Transactions create',
params: { account: account.uuid },
}"
>Create transaction/invoice</v-btn
>
<v-btn
class="ma-1"
:to="{
name: 'Instance create',
params: {
accountId: account.uuid,
},
}"
>
Create instance
</v-btn>
</div>
<div class="d-flex justify-end mt-3 align-center">
<v-switch
Expand Down
1 change: 1 addition & 0 deletions admin-ui/src/components/accounts_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export default {
accounts() {
return this.$store.getters["accounts/all"].map((a) => ({
...a,
balance: a.balance || 0,
currency: a.currency || this.defaultCurrency,
data: {
...a.data,
Expand Down
4 changes: 2 additions & 2 deletions admin-ui/src/components/instances_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default {
return this.getPrice(inst) + " " + this.defaultCurrency;
},
getAccountPrice(inst) {
const accountCurrency = this.getAccount(inst)?.currency;
const accountCurrency = this.getAccount(inst)?.currency || this.defaultCurrency;
return (
(this.getPrice(inst) * this.getRate(accountCurrency)).toFixed(2) +
Expand Down Expand Up @@ -358,7 +358,7 @@ export default {
getExpirationDate(inst) {
if (inst.data.next_payment_date)
return this.date(inst.data.next_payment_date);
return "unknown";
return "-";
},
getService({ service }) {
return (
Expand Down
8 changes: 8 additions & 0 deletions admin-ui/src/components/modules/empty/billingInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
/>
</v-col>

<v-col>
<v-text-field
readonly
label="Start date"
:value="template.data.start || '-'"
/>
</v-col>

<v-col
v-if="
template.billingPlan.title.toLowerCase() !== 'payg' ||
Expand Down
131 changes: 131 additions & 0 deletions admin-ui/src/components/plans_empty_addons_table.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<template>
<nocloud-table
table-name="empty-addons-prices"
class="pa-4"
item-key="id"
v-model="selected"
:show-expand="true"
:items="product.meta.addons ?? []"
:headers="addonsHeaders"
:expanded.sync="expanded"
>
<template v-slot:top>
<v-toolbar flat color="background">
<v-toolbar-title>Addons</v-toolbar-title>
<v-divider inset vertical class="mx-4" />
<v-spacer />

<v-btn class="mr-2" color="background-light" @click="addConfig">
Create
</v-btn>
<confirm-dialog @confirm="removeConfig">
<v-btn color="background-light" :disabled="selected.length < 1">
Delete
</v-btn>
</confirm-dialog>
</v-toolbar>
</template>

<template v-slot:[`item.title`]="{ item }">
<v-text-field
dense
v-model="item.title"
:rules="generalRule"
/>
</template>

<template v-slot:[`item.price`]="{ item }">
<v-text-field
dense
type="number"
:value="item.price"
:suffix="defaultCurrency"
:rules="generalRule"
@input="(value) => item.price = parseFloat(value)"
/>
</template>

<template v-slot:[`item.period`]="{ item }">
<date-field
:period="fullDate[item.id]"
@changeDate="(date) => setPeriod(date.value, item.id)"
/>
</template>

<template v-slot:[`item.public`]="{ item }">
<v-switch v-model="item.public" />
</template>

<template v-slot:expanded-item="{ headers, item }">
<td />
<td :colspan="headers.length - 1">
<v-subheader class="px-0">Description</v-subheader>

<rich-editor class="html-editor" v-model="item.description" />
</td>
</template>
</nocloud-table>
</template>

<script setup>
import { ref } from "vue";
import useCurrency from "@/hooks/useCurrency.js";
import { getFullDate, getTimestamp } from "@/functions.js";
import dateField from "@/components/date.vue";
import nocloudTable from "@/components/table.vue";
import RichEditor from "@/components/ui/richEditor.vue";
import confirmDialog from "@/components/confirmDialog.vue";
const props = defineProps({
product: { type: Object, required: true }
})
const emits = defineEmits(["update:addons"])
const { defaultCurrency } = useCurrency();
const fullDate = ref({})
const selected = ref([])
const expanded = ref([])
const addonsHeaders = [
{ text: "Title", value: "title" },
{ text: "Price", value: "price" },
{ text: "Period", value: "period", width: 400 },
{ text: "Public", value: "public" },
];
const generalRule = [(v) => !!v || "This field is required!"];
function addConfig() {
const addons = JSON.parse(JSON.stringify(props.product.meta.addons ?? []))
addons.push({
id: Math.random().toString(16).slice(2),
description: "",
title: "",
price: 0,
period: 0,
public: true
})
emits("update:addons", addons)
}
function removeConfig() {
const addons = JSON.parse(JSON.stringify(props.product.meta.addons ?? []))
.filter(({ id }) => !selected.value.find((el) => el.id === id))
selected.value = []
emits("update:addons", addons)
}
function setPeriod(value, id) {
const item = props.product.meta.addons.find((addon) => addon.id === id)
fullDate.value[id] = value
item.period = getTimestamp(value)
}
props.product.meta.addons?.forEach(({ period, id }) => {
fullDate.value[id] = getFullDate(period);
});
</script>
25 changes: 23 additions & 2 deletions admin-ui/src/components/plans_products_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@
/>
</v-radio-group>
</template>

<template v-slot:[`item.meta.addons`]="{ item }">
<v-dialog width="90vw">
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on">
<v-icon> mdi-menu-open </v-icon>
</v-btn>
</template>

<plans-empty-addons-table
:product="item"
@update:addons="(value) => $set(item.meta, 'addons', value)"
/>
</v-dialog>
</template>

<template v-slot:expanded-item="{ headers, item }">
<td />
<td :colspan="headers.length - 1">
Expand Down Expand Up @@ -206,6 +222,7 @@ import JsonEditor from "@/components/JsonEditor.vue";
import nocloudTable from "@/components/table.vue";
import plansResourcesTable from "@/components/plans_resources_table.vue";
import plansEmptyTable from "@/components/plans_empty_table.vue";
import plansEmptyAddonsTable from "@/components/plans_empty_addons_table.vue";
import confirmDialog from "@/components/confirmDialog.vue";
import { getFullDate } from "@/functions";
import useCurrency from "@/hooks/useCurrency";
Expand Down Expand Up @@ -237,7 +254,7 @@ const generalRule = [(v) => !!v || "This field is required!"];
const kinds = ["POSTPAID", "PREPAID"];
const tabs = ["Products", "Resources"];
const headers = [
const headers = ref([
{ text: "Key", value: "key" },
{ text: "Title", value: "title" },
{ text: "Price", value: "price", width: 150 },
Expand All @@ -246,7 +263,11 @@ const headers = [
{ text: "Group", value: "group", width: 300 },
{ text: "Public", value: "public" },
{ text: "Sorter", value: "sorter" },
];
]);
if (props.type === "empty") headers.value.push({
text: "Addons", value: "meta.addons"
})
onMounted(() => {
setProductsArray();
Expand Down
15 changes: 14 additions & 1 deletion admin-ui/src/components/reports_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
<template v-slot:[`item.exec`]="{ value }">
<span>{{ new Date(value * 1000).toLocaleString() }}</span>
</template>
<template v-slot:[`item.paymentDate`]="{ value }">
<div class="d-flex justify-center align-center">
{{ value ? new Date(value * 1000).toLocaleString() : "-" }}
</div>
</template>
<template v-slot:[`item.status`]="{ item }">
<div class="d-flex justify-center align-center">
{{ item.paymentDate ? "Paid" : "Unpaid" }}
</div>
</template>
<template v-slot:[`item.service`]="{ value }">
<router-link :to="{ name: 'Service', params: { serviceId: value } }">
{{ getService(value)?.title || value }}
Expand Down Expand Up @@ -116,6 +126,8 @@ const reportsHeaders = computed(() => {
const headers = [
{ text: "Duration", value: "duration" },
{ text: "Executed date", value: "exec" },
{ text: "Payment date", value: "paymentDate" },
{ text: "Status", value: "status" },
{ text: "Total", value: "totalPreview" },
{ text: "Total in default currency", value: "totalDefaultPreview" },
{ text: "Product or resource", value: "item" },
Expand Down Expand Up @@ -185,14 +197,15 @@ const onUpdateOptions = async (newOptions) => {
r.end * 1000
).toLocaleString()}`,
exec: r.exec,
transactionUuid:r.meta?.transaction,
transactionUuid: r.meta?.transaction,
currency: r.currency,
item: r.product || r.resource,
uuid: r.uuid,
service: r.service,
instance: r.instance,
account: r.account,
type: r.meta?.transactionType,
paymentDate: r.meta?.payment_date,
totalDefault: -convertFrom(r.total, r.currency),
};
});
Expand Down
Loading

0 comments on commit 96835d4

Please sign in to comment.