2
0
mirror of https://github.com/frappe/books.git synced 2025-02-03 04:28:32 +00:00

Merge pull request #398 from 18alantom/v1-design-update

incr: V1 design update
This commit is contained in:
Alan 2022-06-10 13:21:47 +05:30 committed by GitHub
commit ba64186d01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 573 additions and 509 deletions

View File

@ -26,7 +26,7 @@ export class Main {
mainWindow: BrowserWindow | null = null; mainWindow: BrowserWindow | null = null;
WIDTH = 1200; WIDTH = 1200;
HEIGHT = process.platform === 'win32' ? 926 : 900; HEIGHT = process.platform === 'win32' ? 826 : 800;
constructor() { constructor() {
this.icon = this.isDevelopment this.icon = this.isDevelopment
@ -77,8 +77,6 @@ export class Main {
const options: BrowserWindowConstructorOptions = { const options: BrowserWindowConstructorOptions = {
width: this.WIDTH, width: this.WIDTH,
height: this.HEIGHT, height: this.HEIGHT,
minWidth: this.WIDTH,
minHeight: this.HEIGHT,
title: this.title, title: this.title,
titleBarStyle: 'hidden', titleBarStyle: 'hidden',
trafficLightPosition: { x: 16, y: 16 }, trafficLightPosition: { x: 16, y: 16 },

View File

@ -1,7 +1,14 @@
<template> <template>
<button <button
class="focus:outline-none rounded-md shadow-button flex-center h-8" class="
:style="style" focus:outline-none
rounded-md
flex
justify-center
items-center
h-8
text-sm
"
:class="_class" :class="_class"
v-bind="$attrs" v-bind="$attrs"
> >
@ -30,21 +37,15 @@ export default {
}, },
}, },
computed: { computed: {
style() {
return {
...(this.padding
? { padding: this.icon ? '6px 12px' : '6px 24px' }
: {}),
color: this.type === 'primary' ? '#fff' : '#112B42',
'background-image':
this.type === 'primary'
? 'linear-gradient(180deg, #2C9AF1 0%, #2490EF 100%)'
: 'linear-gradient(180deg, #F9F9FA 0%, #F4F4F6 100%)',
};
},
_class() { _class() {
return { return {
'opacity-50 cursor-not-allowed pointer-events-none': this.disabled, 'opacity-50 cursor-not-allowed pointer-events-none': this.disabled,
'text-white': this.type === 'primary',
'bg-blue-500': this.type === 'primary',
'text-gray-900': this.type !== 'primary',
'bg-gray-100': this.type !== 'primary',
'px-3': this.padding && this.icon,
'px-6': this.padding && !this.icon,
}; };
}, },
}, },

View File

@ -357,6 +357,6 @@ export default {
<style scoped> <style scoped>
rect:hover { rect:hover {
filter: brightness(115%); filter: brightness(105%);
} }
</style> </style>

View File

@ -53,16 +53,12 @@
@mouseover="$emit('change', i)" @mouseover="$emit('change', i)"
/> />
</template> </template>
</svg> <text
<div :x="cx"
class="text-center w-28 relative" :y="cy"
:style="{ text-anchor="middle"
top: `calc(-50% + ${textOffsetY}px)`, style="font-size: 6px; font-weight: bold; fill: #415668"
left: `calc(50% + ${textOffsetX}px)`, >
transform: 'translateX(-50%)',
}"
>
<p class="text-base font-bold whitespace-nowrap">
{{ {{
valueFormatter( valueFormatter(
active !== null && sectors.length !== 0 active !== null && sectors.length !== 0
@ -71,23 +67,20 @@
'Currency' 'Currency'
) )
}} }}
</p> </text>
<p <text
class=" :x="cx"
text-xs text-gray-600 :y="cy + 8"
font-semibold text-anchor="middle"
whitespace-nowrap style="font-size: 5px; fill: #a1abb4"
overflow-x-auto
no-scrollbar
"
> >
{{ {{
active !== null && sectors.length !== 0 active !== null && sectors.length !== 0
? sectors[active].label ? sectors[active].label
: totalLabel : totalLabel
}} }}
</p> </text>
</div> </svg>
</div> </div>
</template> </template>

View File

@ -5,16 +5,21 @@
</div> </div>
<!-- Title Row --> <!-- Title Row -->
<Row :ratio="ratio" class="border-b px-2 text-gray-600 w-full"> <Row
:ratio="ratio"
class="border-b px-2 text-gray-600 w-full flex items-center"
>
<div class="flex items-center pl-2">#</div> <div class="flex items-center pl-2">#</div>
<div <div
class="items-center flex px-2 h-row-mid"
:class="{ :class="{
'px-2 py-3': size === 'small', 'ml-auto': isNumeric(df),
'px-3 py-4': size !== 'small',
'text-right': isNumeric(df),
}" }"
v-for="df in tableFields" v-for="df in tableFields"
:key="df.fieldname" :key="df.fieldname"
:style="{
height: ``,
}"
> >
{{ df.label }} {{ df.label }}
</div> </div>
@ -40,29 +45,28 @@
<!-- Add Row and Row Count --> <!-- Add Row and Row Count -->
<Row <Row
:ratio="ratio" :ratio="ratio"
class="text-gray-500 cursor-pointer border-transparent px-2 w-full" class="
text-gray-500
cursor-pointer
border-transparent
px-2
w-full
h-row-mid
flex
items-center
"
v-if="!isReadOnly" v-if="!isReadOnly"
@click="addRow" @click="addRow"
> >
<div class="flex items-center pl-1"> <div class="flex items-center pl-1">
<feather-icon name="plus" class="w-4 h-4 text-gray-500" /> <feather-icon name="plus" class="w-4 h-4 text-gray-500" />
</div> </div>
<div <div class="flex justify-between px-2">
class="flex justify-between"
:class="{
'px-2 py-3': size === 'small',
'px-3 py-4': size !== 'small',
}"
>
{{ t`Add Row` }} {{ t`Add Row` }}
</div> </div>
<div v-for="i in ratio.slice(3).length" :key="i"></div> <div v-for="i in ratio.slice(3).length" :key="i"></div>
<div <div
class="text-right" class="text-right px-2"
:class="{
'px-2 py-3': size === 'small',
'px-3 py-4': size !== 'small',
}"
v-if=" v-if="
value && maxRowsBeforeOverflow && value.length > maxRowsBeforeOverflow value && maxRowsBeforeOverflow && value.length > maxRowsBeforeOverflow
" "
@ -161,6 +165,11 @@ export default {
}, },
}, },
computed: { computed: {
height() {
if (this.size === 'small') {
}
return 2;
},
ratio() { ratio() {
return [0.3].concat(this.tableFields.map(() => 1)); return [0.3].concat(this.tableFields.map(() => 1));
}, },

View File

@ -1,5 +1,18 @@
<template> <template>
<Row :ratio="ratio" class="w-full px-2 border-b hover:bg-brand-100 group"> <Row
:ratio="ratio"
class="
w-full
px-2
border-b
hover:bg-gray-50
h-row-mid
group
flex
items-center
justify-center
"
>
<!-- Index or Remove button --> <!-- Index or Remove button -->
<div class="flex items-center pl-2 text-gray-600"> <div class="flex items-center pl-2 text-gray-600">
<span class="hidden group-hover:inline-block"> <span class="hidden group-hover:inline-block">
@ -18,7 +31,6 @@
<FormControl <FormControl
v-for="df in tableFields" v-for="df in tableFields"
:size="size" :size="size"
class="py-2"
:read-only="readOnly" :read-only="readOnly"
:input-class="{ 'text-right': isNumeric(df), 'bg-transparent': true }" :input-class="{ 'text-right': isNumeric(df), 'bg-transparent': true }"
:key="df.fieldname" :key="df.fieldname"

View File

@ -7,12 +7,7 @@
right right
> >
<template v-slot="{ toggleDropdown }"> <template v-slot="{ toggleDropdown }">
<Button <Button :type="type" :icon="icon" @click="toggleDropdown()">
class="text-gray-900"
:type="type"
:icon="true"
@click="toggleDropdown()"
>
<slot> <slot>
<feather-icon name="more-horizontal" class="w-4 h-4" /> <feather-icon name="more-horizontal" class="w-4 h-4" />
</slot> </slot>
@ -30,6 +25,7 @@ export default {
props: { props: {
actions: { default: [] }, actions: { default: [] },
type: { type: String, default: 'secondary' }, type: { type: String, default: 'secondary' },
icon: { type: Boolean, default: true },
}, },
inject: { inject: {
doc: { default: null }, doc: { default: null },

View File

@ -4,7 +4,7 @@
<Button :icon="true" @click="togglePopover()"> <Button :icon="true" @click="togglePopover()">
<span class="flex items-center"> <span class="flex items-center">
<Icon name="filter" size="12" class="stroke-current text-gray-800" /> <Icon name="filter" size="12" class="stroke-current text-gray-800" />
<span class="ml-2 text-base text-black"> <span class="ml-1">
<template v-if="activeFilterCount > 0"> <template v-if="activeFilterCount > 0">
{{ filterAppliedMessage }} {{ filterAppliedMessage }}
</template> </template>

View File

@ -0,0 +1,35 @@
<template>
<div class="flex flex-col bg-gray-25">
<!-- Page Header (Title, Buttons, etc) -->
<PageHeader :backLink="backLink" :title="title" :border="false">
<slot name="header" />
</PageHeader>
<!-- Invoice Form -->
<div
class="
border
rounded-lg
shadow-lg
flex flex-col
self-center
w-form
h-full
mb-4
bg-white
"
>
<slot name="body" />
</div>
</div>
</template>
<script>
import PageHeader from './PageHeader.vue';
export default {
components: { PageHeader },
props: {
backLink: { type: Boolean, default: false },
title: { type: String, default: '' },
},
};
</script>

View File

@ -1,14 +1,16 @@
<script> <script>
import { uicolors } from 'src/utils/colors';
export default { export default {
name: 'IconBase', name: 'IconBase',
props: ['active'], props: ['active'],
computed: { computed: {
lightColor() { lightColor() {
return this.active ? '#8CC0F1' : '#A1ABB4'; return this.active ? uicolors.blue['300'] : uicolors.gray['400'];
}, },
darkColor() { darkColor() {
return this.active ? '#4794E9' : '#415668'; return this.active ? uicolors.blue['500'] : uicolors.gray['700'];
} },
} },
}; };
</script> </script>

View File

@ -1,12 +1,23 @@
<template> <template>
<div class="my-4 mx-4 flex justify-between window-drag"> <div
<h1 class="text-2xl font-bold select-none" v-if="title && !backLink"> class="
px-4
flex
justify-between
window-drag
items-center
h-row-largest
flex-shrink-0
"
:class="border ? 'border-b' : ''"
>
<h1 class="text-xl font-semibold select-none" v-if="title && !backLink">
{{ title }} {{ title }}
</h1> </h1>
<BackLink v-if="backLink" class="window-no-drag"/> <BackLink v-if="backLink" class="window-no-drag" />
<div class="flex items-stretch window-no-drag gap-2"> <div class="flex items-stretch window-no-drag gap-2">
<slot /> <slot />
<SearchBar v-if="!hideSearch"/> <SearchBar v-if="!hideSearch" />
</div> </div>
</div> </div>
</template> </template>
@ -19,6 +30,7 @@ export default {
title: { type: String, default: '' }, title: { type: String, default: '' },
backLink: { type: Boolean, default: false }, backLink: { type: Boolean, default: false },
hideSearch: { type: Boolean, default: false }, hideSearch: { type: Boolean, default: false },
border: { type: Boolean, default: true },
}, },
components: { SearchBar, BackLink }, components: { SearchBar, BackLink },
}; };

View File

@ -1,5 +1,8 @@
<template> <template>
<div class="my-3 grid grid-cols-3 text-gray-800 text-sm select-none"> <div
class="grid grid-cols-3 text-gray-800 text-sm select-none items-center"
style="height: 50px"
>
<!-- Length Display --> <!-- Length Display -->
<div class="justify-self-start"> <div class="justify-self-start">
{{ {{

View File

@ -1,93 +0,0 @@
<template>
<div id="importWizard" class="modal-body" style="overflow: hidden;">
<div class="row">
<div class="col-12">
<!-- <div v-for="(entry, i) in entries" :key="i">{{ entry['Date'] }}</div> -->
<table class="table table-sm">
<thead style="font-size: 13px">
<tr>
<th scope="col">
<input type="checkbox" checked="true" ref="all" @change="allSelected" />
</th>
<th
scope="col"
v-for="(fieldname, index) in Object.keys(entries[0])"
:key="index"
>{{ fieldname }}</th>
</tr>
</thead>
<tbody style="font-size: 13px">
<tr v-for="(entry, index) in entries" :key="index">
<th scope="row">
<input type="checkbox" checked="true" :ref="'cb-'+index" @change="rowSelected" />
</th>
<td v-for="(fieldname, idx) in Object.keys(entry)" :key="idx">{{ entry[fieldname] }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-12 text-right">
<f-button primary @click="reconcile">{{ 'Reconcile' }}</f-button>
</div>
</div>
</div>
</template>
<script>
import luxon from 'luxon';
import { fyo } from 'src/initFyo';
export default {
props: ['entries', 'afterReconcile'],
data() {
return {
selectedEntries: []
};
},
methods: {
allSelected() {
for (let i = 0; i < this.entries.length; i++) {
this.$refs['cb-' + i][0].checked = this.$refs['all'].checked;
}
},
rowSelected() {
for (let i = 0; i < this.entries.length; i++) {
if (!this.$refs['cb-' + i][0].checked) {
this.$refs['all'].checked = false;
}
}
},
close() {
this.$modal.hide();
},
async reconcile() {
for (let i = 0; i < this.entries.length; i++) {
if (this.$refs['cb-' + i][0].checked)
this.selectedEntries.push(this.entries[i]);
}
for (let entry of this.selectedEntries) {
const payment = await fyo.doc.getDoc('Payment', entry['Payment Entry']);
const clearanceDate =
luxon.DateTime.fromFormat(
entry['Clearance Date'],
'dd/MM/yy'
).toISO() ||
luxon.DateTime.fromFormat(
entry['Clearance Date'],
'dd/MM/yyyy'
).toISO();
payment.set({ clearanceDate });
await payment.sync();
}
this.close();
await this.afterReconcile();
}
}
};
</script>
<style>
.modal-dialog {
max-width: 600px !important;
}
</style>

View File

@ -4,9 +4,12 @@
<div class="overflow-hidden" v-if="dataSlice.length"> <div class="overflow-hidden" v-if="dataSlice.length">
<!--Title Row --> <!--Title Row -->
<div <div
class="w-full overflow-x-hidden flex items-center border-b" class="w-full overflow-x-hidden flex items-center border-b px-4"
ref="titlerow" ref="titlerow"
:style="{ height: `${hconst}px`, paddingRight: '8px' }" :style="{
height: `${hconst}px`,
paddingRight: 'calc(var(--w-scrollbar) + 1rem)',
}"
> >
<div <div
v-for="(col, c) in report.columns" v-for="(col, c) in report.columns"
@ -33,11 +36,14 @@
<template v-for="(row, r) in dataSlice" :key="r + '-row'"> <template v-for="(row, r) in dataSlice" :key="r + '-row'">
<div <div
v-if="!row.folded" v-if="!row.folded"
class="flex items-center w-max" class="flex items-center w-max px-4"
:style="{ height: `${hconst}px` }" :style="{
height: `${hconst}px`,
minWidth: `calc(var(--w-desk) - var(--w-scrollbar))`,
}"
:class="[ :class="[
r !== pageEnd - 1 ? 'border-b' : '', r !== pageEnd - 1 ? 'border-b' : '',
row.isGroup ? 'hover:bg-gray-100 cursor-pointer' : '', row.isGroup ? 'hover:bg-gray-50 cursor-pointer' : '',
]" ]"
@click="() => onRowClick(row, r)" @click="() => onRowClick(row, r)"
> >
@ -70,6 +76,7 @@
<hr /> <hr />
<Paginator <Paginator
:item-count="report?.reportData?.length ?? 0" :item-count="report?.reportData?.length ?? 0"
class="px-4"
@index-change="setPageIndices" @index-change="setPageIndices"
/> />
</div> </div>
@ -140,7 +147,7 @@ export default defineComponent({
} }
if (cell.italics) { if (cell.italics) {
styles['font-style'] = 'italic'; styles['font-style'] = 'oblique 15deg';
} }
if (i === 0) { if (i === 0) {

View File

@ -1,29 +1,13 @@
<template> <template>
<div> <div>
<!-- Search Bar Button --> <!-- Search Bar Button -->
<button <Button @click="open" class="px-2" :padding="false">
@click="open" <feather-icon name="search" class="w-4 h-4 mr-1 text-gray-800" />
class="
focus:outline-none
shadow-button
flex flex-row
gap-1
text-base text-gray-700
bg-gray-100
rounded-md
h-8
w-48
px-3
items-center
hover:bg-gray-200
"
>
<feather-icon name="search" class="w-4 h-4" />
<p>{{ t`Search` }}</p> <p>{{ t`Search` }}</p>
<div class="text-gray-400 ml-auto text-sm"> <div class="text-gray-500 px-1 ml-4 text-sm">
{{ modKey('k') }} {{ modKey('k') }}
</div> </div>
</button> </Button>
</div> </div>
<!-- Search Modal --> <!-- Search Modal -->
@ -71,7 +55,7 @@
<div <div
v-if="si.group === 'Docs'" v-if="si.group === 'Docs'"
class="flex w-full justify-between px-3 items-center" class="flex w-full justify-between px-3 items-center"
style="height: 48px; margin-left: -2px" style="height: var(--h-row-mid); margin-left: -2px"
> >
<div class="flex items-center"> <div class="flex items-center">
<p class="text-gray-900"> <p class="text-gray-900">
@ -93,7 +77,7 @@
<div <div
v-else v-else
class="flex flex-row w-full justify-between px-3 items-center" class="flex flex-row w-full justify-between px-3 items-center"
style="height: 48px; margin-left: -2px" style="height: var(--h-row-mid); margin-left: -2px"
> >
<p class="text-gray-900"> <p class="text-gray-900">
{{ si.label }} {{ si.label }}
@ -126,7 +110,7 @@
</button> </button>
</div> </div>
<button <button
class="hover:bg-gray-100 px-2 py-0.5 rounded text-gray-800" class="hover:bg-gray-50 px-2 py-0.5 rounded text-gray-800"
@click="showMore = !showMore" @click="showMore = !showMore"
> >
{{ showMore ? t`Less Filters` : t`More Filters` }} {{ showMore ? t`Less Filters` : t`More Filters` }}
@ -215,6 +199,7 @@ import { getGroupLabelMap, searchGroups } from 'src/utils/search';
import { useKeys } from 'src/utils/vueUtils'; import { useKeys } from 'src/utils/vueUtils';
import { getIsNullOrUndef } from 'utils/'; import { getIsNullOrUndef } from 'utils/';
import { nextTick, watch } from 'vue'; import { nextTick, watch } from 'vue';
import Button from './Button.vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
export default { export default {
@ -234,7 +219,7 @@ export default {
}; };
}, },
inject: ['searcher'], inject: ['searcher'],
components: { Modal }, components: { Modal, Button },
async mounted() { async mounted() {
if (fyo.store.isDevelopment) { if (fyo.store.isDevelopment) {
window.search = this; window.search = this;

View File

@ -1,6 +1,6 @@
<template> <template>
<div <div
class="p-2 h-full flex justify-between flex-col bg-gray-100" class="p-2 h-full flex justify-between flex-col bg-gray-25"
:class="{ :class="{
'window-drag': platform !== 'Windows', 'window-drag': platform !== 'Windows',
}" }"
@ -13,30 +13,15 @@
> >
<h6 <h6
class=" class="
text-xl
font-semibold font-semibold
whitespace-nowrap whitespace-nowrap
overflow-auto overflow-auto
no-scrollbar no-scrollbar
select-none select-none
w-32
" "
> >
{{ companyName }} {{ companyName }}
</h6> </h6>
<feather-icon
class="
w-5
h-5
ml-1
stroke-2
cursor-pointer
text-gray-600
hover:text-gray-800
"
name="chevron-down"
@click="$emit('change-db-file')"
/>
</div> </div>
<!-- Sidebar Items --> <!-- Sidebar Items -->
@ -49,9 +34,9 @@
items-center items-center
rounded-md rounded-md
cursor-pointer cursor-pointer
hover:bg-white hover:bg-gray-100
" "
:class="isActiveGroup(group) && !group.items ? 'bg-white' : ''" :class="isActiveGroup(group) && !group.items ? 'bg-gray-100' : ''"
@click="onGroupClick(group)" @click="onGroupClick(group)"
> >
<Icon <Icon
@ -81,7 +66,7 @@
pl-10 pl-10
rounded rounded
cursor-pointer cursor-pointer
hover:bg-white hover:bg-gray-100
" "
:class="itemActiveClass(item)" :class="itemActiveClass(item)"
@click="onItemClick(item)" @click="onItemClick(item)"
@ -93,17 +78,42 @@
</div> </div>
<!-- Report Issue and App Version --> <!-- Report Issue and App Version -->
<div class="px-5 window-no-drag"> <div class="window-no-drag flex flex-col gap-2 p-2">
<p v-if="fyo.store.isDevelopment" class="text-sm text-gray-600">
Development
</p>
<button <button
class="pb-1 text-sm text-gray-600 hover:text-gray-800 w-full text-left" class="
flex
text-sm text-gray-600
hover:text-gray-800
gap-1
items-center
"
@click="() => reportIssue()" @click="() => reportIssue()"
> >
{{ t`Report Issue` }} <feather-icon name="flag" class="h-4 w-4" />
<p>
{{ t`Report Issue` }}
</p>
</button> </button>
<p class="pb-3 text-sm text-gray-600 select-none">v{{ appVersion }}</p>
<button
class="
flex
text-sm text-gray-600
hover:text-gray-800
gap-1
items-center
"
@click="$emit('change-db-file')"
>
<feather-icon name="database" class="h-4 w-4" />
<p>{{ t`Change DB` }}</p>
</button>
<p
v-if="fyo.store.isDevelopment"
class="text-xs text-gray-500 select-none"
>
dev mode
</p>
</div> </div>
</div> </div>
</template> </template>
@ -179,7 +189,7 @@ export default {
let routeMatch = currentRoute === item.route; let routeMatch = currentRoute === item.route;
let schemaNameMatch = let schemaNameMatch =
item.schemaName && params.schemaName === item.schemaName; item.schemaName && params.schemaName === item.schemaName;
return routeMatch || schemaNameMatch ? 'bg-white text-blue-500' : ''; return routeMatch || schemaNameMatch ? 'bg-gray-100 text-blue-500' : '';
}, },
isActiveGroup(group) { isActiveGroup(group) {
return this.activeGroup && group.label === this.activeGroup.label; return this.activeGroup && group.label === this.activeGroup.label;

View File

@ -1,5 +1,5 @@
<template> <template>
<Badge class="text-xs flex-center px-3 ml-2" :color="color" v-if="status">{{ <Badge class="text-sm flex-center px-3 ml-2" :color="color" v-if="status">{{
statusLabel statusLabel
}}</Badge> }}</Badge>
</template> </template>

View File

@ -20,6 +20,8 @@
:key="`${df.fieldname}-inline`" :key="`${df.fieldname}-inline`"
> >
<TwoColumnForm <TwoColumnForm
class="overflow-auto"
style="max-height: calc((var(--h-row-mid) + 1px) * 3 - 1px)"
ref="inlineEditForm" ref="inlineEditForm"
:doc="inlineEditDoc" :doc="inlineEditDoc"
:fields="getInlineEditFields(df)" :fields="getInlineEditFields(df)"
@ -29,13 +31,16 @@
:autosave="false" :autosave="false"
@error="(msg) => $emit('error', msg)" @error="(msg) => $emit('error', msg)"
/> />
<div class="flex px-4 pb-2 gap-2"> <div
<Button class="w-1/2 text-gray-900" @click="stopInlineEditing"> class="flex px-4 py-4 justify-between items-center"
style="max-height: calc(var(--h-row-mid) + 1px)"
>
<Button class="text-gray-900 w-20" @click="stopInlineEditing">
{{ t`Cancel` }} {{ t`Cancel` }}
</Button> </Button>
<Button <Button
type="primary" type="primary"
class="w-1/2 text-white" class="text-white w-20"
@click="saveInlineEditDoc(df)" @click="saveInlineEditDoc(df)"
> >
{{ t`Save` }} {{ t`Save` }}
@ -49,12 +54,13 @@
class="grid items-center" class="grid items-center"
:class="{ :class="{
'border-b': !noBorder, 'border-b': !noBorder,
'h-12':
!['AttachImage', 'Text'].includes(df.fieldtype) &&
!errors[df.fieldname],
}" }"
:key="`${df.fieldname}-regular`" :key="`${df.fieldname}-regular`"
:style="style" :style="{
...style,
height: getFieldHeight(df),
}"
> >
<div class="py-2 pl-4 flex text-gray-600"> <div class="py-2 pl-4 flex text-gray-600">
<div class="py-1"> <div class="py-1">
@ -76,6 +82,7 @@
:value="getRegularValue(df)" :value="getRegularValue(df)"
:class="{ 'p-2': df.fieldtype === 'Check' }" :class="{ 'p-2': df.fieldtype === 'Check' }"
:read-only="evaluateReadOnly(df)" :read-only="evaluateReadOnly(df)"
input-class="bg-transparent"
@change="async (value) => await onChange(df, value)" @change="async (value) => await onChange(df, value)"
@focus="activateInlineEditing(df)" @focus="activateInlineEditing(df)"
@new-doc="async (newdoc) => await onChange(df, newdoc.name)" @new-doc="async (newdoc) => await onChange(df, newdoc.name)"
@ -149,6 +156,17 @@ export default {
} }
}, },
methods: { methods: {
getFieldHeight(df) {
if (['AttachImage', 'Text'].includes(df.fieldtype)) {
return 'calc((var(--h-row-mid) + 1px) * 2)';
}
if (this.errors[df.fieldname]) {
return 'calc((var(--h-row-mid) + 1px) * 2)';
}
return 'calc(var(--h-row-mid) + 1px)';
},
getRegularValue(df) { getRegularValue(df) {
if (!df.inline) { if (!df.inline) {
return this.doc[df.fieldname]; return this.doc[df.fieldname];

View File

@ -1,12 +1,21 @@
<template> <template>
<div class="py-4" v-if="pendingInvoices.length"> <div v-if="pendingInvoices.length">
<div class="px-4 text-sm text-gray-600"> <div
class="
px-4
text-sm text-gray-600
border-b
flex
items-center
h-row-smallest
"
>
{{ t`Recent Invoices` }} {{ t`Recent Invoices` }}
</div> </div>
<!-- Invoice List --> <!-- Invoice List -->
<div <div
class="px-4 py-3 border-b hover:bg-gray-100 cursor-pointer text-base" class="px-4 py-4 border-b hover:bg-gray-50 cursor-pointer text-base"
v-for="invoice in pendingInvoices" v-for="invoice in pendingInvoices"
:key="invoice.name" :key="invoice.name"
@click="routeToForm(invoice)" @click="routeToForm(invoice)"
@ -22,13 +31,13 @@
</div> </div>
<!-- Invoice Date & Amount --> <!-- Invoice Date & Amount -->
<div class="flex justify-between"> <div class="flex justify-between text-gray-900">
<span> <span>
{{ fyo.format(invoice.date, getInvoiceField(invoice, 'date')) }} {{ fyo.format(invoice.date, getInvoiceField(invoice, 'date')) }}
</span> </span>
<div> <div>
<!-- Paid Amount --> <!-- Paid Amount -->
<span class="font-medium text-gray-900"> <span>
{{ {{
fyo.format( fyo.format(
amountPaid(invoice), amountPaid(invoice),
@ -38,7 +47,7 @@
</span> </span>
<!-- Outstanding Amount --> <!-- Outstanding Amount -->
<span class="text-gray-600" v-if="!fullyPaid(invoice)"> <span class="text-gray-600 font-medium" v-if="!fullyPaid(invoice)">
({{ ({{
fyo.format( fyo.format(
invoice.outstandingAmount, invoice.outstandingAmount,

View File

@ -25,8 +25,8 @@ export default {
<style> <style>
.scroll-container::-webkit-scrollbar { .scroll-container::-webkit-scrollbar {
width: 8px; width: var(--w-scrollbar);
height: 8px; height: var(--w-scrollbar);
} }
.scroll-container::-webkit-scrollbar-thumb { .scroll-container::-webkit-scrollbar-thumb {
background-color: theme('colors.gray.100'); background-color: theme('colors.gray.100');

View File

@ -3,31 +3,33 @@
<PageHeader :title="t`Chart of Accounts`" /> <PageHeader :title="t`Chart of Accounts`" />
<!-- Chart of Accounts --> <!-- Chart of Accounts -->
<div class="flex-1 flex flex-col mx-4 overflow-y-auto mb-4" v-if="root"> <div class="flex-1 flex flex-col overflow-y-auto mb-4" v-if="root">
<!-- Chart of Accounts Indented List --> <!-- Chart of Accounts Indented List -->
<template v-for="account in allAccounts" :key="account.name"> <template v-for="account in allAccounts" :key="account.name">
<!-- Account List Item --> <!-- Account List Item -->
<div <div
class=" class="
mt-2
py-2 py-2
cursor-pointer cursor-pointer
hover:bg-gray-100 hover:bg-gray-50
group group
flex flex
items-center items-center
border-b
flex-shrink-0
pr-4
" "
:class="[ :class="[
account.level !== 0 ? 'text-base' : 'text-lg', account.level !== 0 ? 'text-base' : 'text-lg',
isQuickEditOpen(account) ? 'bg-gray-200' : '', isQuickEditOpen(account) ? 'bg-gray-200' : '',
`pl-${account.level * 8}`,
]" ]"
:style="`height: calc(var(--h-row-mid) + 1px); padding-left: calc(1rem + 2rem * ${account.level})`"
@click="onClick(account)" @click="onClick(account)"
> >
<component :is="getIconComponent(account)" class="ml-2" /> <component :is="getIconComponent(account)" />
<div class="flex items-baseline"> <div class="flex items-baseline">
<div <div
class="ml-3" class="ml-4"
:class="[!account.parentAccount && 'font-semibold']" :class="[!account.parentAccount && 'font-semibold']"
> >
{{ account.name }} {{ account.name }}
@ -69,25 +71,24 @@
<div <div
v-if="account.addingAccount || account.addingGroupAccount" v-if="account.addingAccount || account.addingGroupAccount"
class=" class="
mt-2
px-4 px-4
py-2 border-b
cursor-pointer cursor-pointer
hover:bg-gray-100 hover:bg-gray-50
rounded-md
group group
flex flex
items-center items-center
text-base
" "
:class="`${account.level !== 0 ? 'text-base' : 'text-lg'} pl-${ :style="`height: calc(var(--h-row-mid) + 1px); padding-left: calc(1rem + 2rem * ${
(account.level + 1) * 8 account.level + 1
}`" })`"
:key="account.name + '-adding-account'" :key="account.name + '-adding-account'"
> >
<component <component
:is="getIconComponent({ isGroup: account.addingGroupAccount })" :is="getIconComponent({ isGroup: account.addingGroupAccount })"
/> />
<div class="flex items-baseline ml-3"> <div class="flex ml-4 h-row-mid items-center">
<input <input
class="focus:outline-none bg-transparent" class="focus:outline-none bg-transparent"
:class="{ 'text-gray-600': insertingAccount }" :class="{ 'text-gray-600': insertingAccount }"

View File

@ -2,17 +2,17 @@
<div> <div>
<!-- Title and Period Selector --> <!-- Title and Period Selector -->
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="font-medium">{{ t`Cashflow` }}</div> <div class="font-medium text-base">{{ t`Cashflow` }}</div>
<!-- Chart Legend --> <!-- Chart Legend -->
<div class="flex text-base" v-if="hasData"> <div class="flex text-base gap-8" v-if="hasData">
<div class="flex items-center"> <div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-sm inline-block bg-blue-500"></span> <span class="w-3 h-3 rounded-sm inline-block bg-blue-500" />
<span class="ml-2 text-gray-900">{{ t`Inflow` }}</span> <span class="text-gray-900">{{ t`Inflow` }}</span>
</div> </div>
<div class="flex items-center ml-6"> <div class="flex items-center gap-2">
<span class="w-3 h-3 rounded-sm inline-block bg-gray-500"></span> <span class="w-3 h-3 rounded-sm inline-block bg-pink-500" />
<span class="ml-2 text-gray-900">{{ t`Outflow` }}</span> <span class="text-gray-900">{{ t`Outflow` }}</span>
</div> </div>
</div> </div>
<div v-else class="w-16 h-5 bg-gray-200 rounded" /> <div v-else class="w-16 h-5 bg-gray-200 rounded" />
@ -28,7 +28,9 @@
<!-- Line Chart --> <!-- Line Chart -->
<LineChart <LineChart
class="mt-4"
v-if="chartData.points.length" v-if="chartData.points.length"
:aspect-ratio="4.15"
:colors="chartData.colors" :colors="chartData.colors"
:points="chartData.points" :points="chartData.points"
:x-labels="chartData.xLabels" :x-labels="chartData.xLabels"
@ -46,6 +48,7 @@ import { ModelNameEnum } from 'models/types';
import LineChart from 'src/components/Charts/LineChart.vue'; import LineChart from 'src/components/Charts/LineChart.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { formatXLabels, getYMax } from 'src/utils/chart'; import { formatXLabels, getYMax } from 'src/utils/chart';
import { uicolors } from 'src/utils/colors';
import { getDatesAndPeriodList } from 'src/utils/misc'; import { getDatesAndPeriodList } from 'src/utils/misc';
import { getMapFromList } from 'utils/'; import { getMapFromList } from 'utils/';
import PeriodSelector from './PeriodSelector'; import PeriodSelector from './PeriodSelector';
@ -74,10 +77,10 @@ export default {
computed: { computed: {
chartData() { chartData() {
let data = this.data; let data = this.data;
let colors = ['#2490EF', '#B7BFC6']; let colors = [uicolors.blue['500'], uicolors.pink['500']];
if (!this.hasData) { if (!this.hasData) {
data = dummyData; data = dummyData;
colors = ['#E9EBED', '#DFE1E2']; colors = [uicolors.gray['200'], uicolors.gray['100']];
} }
const xLabels = data.map((cf) => cf['yearmonth']); const xLabels = data.map((cf) => cf['yearmonth']);

View File

@ -1,15 +1,21 @@
<template> <template>
<div class="flex flex-col"> <div class="overflow-hidden h-screen" style="width: var(--w-desk)">
<PageHeader :title="t`Dashboard`" /> <PageHeader :title="t`Dashboard`" />
<div class="mx-4 overflow-y-auto no-scrollbar flex flex-col gap-8"> <div class="no-scrollbar overflow-auto h-full">
<Cashflow class="" /> <div
<hr /> style="min-width: var(--w-desk-fixed); min-height: var(--h-app)"
<UnpaidInvoices /> class="overflow-auto"
<hr /> >
<div class="flex gap-8"> <Cashflow class="p-4" />
<ProfitAndLoss class="w-full" /> <hr />
<Expenses class="w-full" /> <UnpaidInvoices />
<hr />
<div class="flex">
<ProfitAndLoss class="w-full p-4 border-r" />
<Expenses class="w-full p-4" />
</div>
<hr />
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,9 +6,10 @@
<PeriodSelector :value="period" @change="(value) => (period = value)" /> <PeriodSelector :value="period" @change="(value) => (period = value)" />
</template> </template>
</SectionHeader> </SectionHeader>
<div class="flex relative" v-show="hasData"> <div class="flex relative" v-show="hasData">
<!-- Chart Legend --> <!-- Chart Legend -->
<div class="w-1/2 flex flex-col gap-5 mt-8"> <div class="w-1/2 flex flex-col gap-4 justify-center">
<!-- Ledgend Item --> <!-- Ledgend Item -->
<div <div
class="flex items-center text-sm" class="flex items-center text-sm"
@ -27,11 +28,11 @@
</div> </div>
</div> </div>
<DonutChart <DonutChart
class="w-1/2" class="w-1/2 my-auto"
:active="active" :active="active"
:sectors="sectors" :sectors="sectors"
:offset-x="3" :offset-x="3"
:thickness="11.5" :thickness="10"
:text-offset-x="6.5" :text-offset-x="6.5"
:value-formatter="(value) => fyo.format(value, 'Currency')" :value-formatter="(value) => fyo.format(value, 'Currency')"
:total-label="t`Total Spending`" :total-label="t`Total Spending`"
@ -52,8 +53,9 @@
</template> </template>
<script> <script>
import { truncate } from 'lodash';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import theme from 'src/theme'; import { uicolors } from 'src/utils/colors';
import { getDatesAndPeriodList } from 'src/utils/misc'; import { getDatesAndPeriodList } from 'src/utils/misc';
import DonutChart from '../../components/Charts/DonutChart.vue'; import DonutChart from '../../components/Charts/DonutChart.vue';
import PeriodSelector from './PeriodSelector'; import PeriodSelector from './PeriodSelector';
@ -72,7 +74,7 @@ export default {
expenses: [], expenses: [],
}), }),
watch: { watch: {
period(new_, old) { period() {
this.setData(); this.setData();
}, },
}, },
@ -89,7 +91,7 @@ export default {
sectors() { sectors() {
return this.expenses.map(({ account, color, total }) => ({ return this.expenses.map(({ account, color, total }) => ({
color, color,
label: account, label: truncate(account, { length: 21 }),
value: total, value: total,
})); }));
}, },
@ -103,11 +105,11 @@ export default {
); );
const shades = [ const shades = [
{ class: 'bg-gray-800', hex: theme.backgroundColor.gray['800'] }, { class: 'bg-pink-500', hex: uicolors.pink['500'] },
{ class: 'bg-gray-600', hex: theme.backgroundColor.gray['600'] }, { class: 'bg-pink-400', hex: uicolors.pink['400'] },
{ class: 'bg-gray-400', hex: theme.backgroundColor.gray['400'] }, { class: 'bg-pink-300', hex: uicolors.pink['300'] },
{ class: 'bg-gray-300', hex: theme.backgroundColor.gray['300'] }, { class: 'bg-pink-200', hex: uicolors.pink['200'] },
{ class: 'bg-gray-200', hex: theme.backgroundColor.gray['200'] }, { class: 'bg-pink-100', hex: uicolors.pink['100'] },
]; ];
topExpenses = topExpenses topExpenses = topExpenses

View File

@ -11,7 +11,9 @@
</template> </template>
</SectionHeader> </SectionHeader>
<BarChart <BarChart
class="mt-4"
v-if="hasData" v-if="hasData"
:aspect-ratio="2.05"
:colors="chartData.colors" :colors="chartData.colors"
:points="chartData.points" :points="chartData.points"
:x-labels="chartData.xLabels" :x-labels="chartData.xLabels"
@ -31,6 +33,7 @@
import BarChart from 'src/components/Charts/BarChart.vue'; import BarChart from 'src/components/Charts/BarChart.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { formatXLabels, getYMax, getYMin } from 'src/utils/chart'; import { formatXLabels, getYMax, getYMin } from 'src/utils/chart';
import { uicolors } from 'src/utils/colors';
import { getDatesAndPeriodList } from 'src/utils/misc'; import { getDatesAndPeriodList } from 'src/utils/misc';
import { getValueMapFromList } from 'utils'; import { getValueMapFromList } from 'utils';
import PeriodSelector from './PeriodSelector'; import PeriodSelector from './PeriodSelector';
@ -57,7 +60,9 @@ export default {
computed: { computed: {
chartData() { chartData() {
const points = [this.data.map((d) => d.balance)]; const points = [this.data.map((d) => d.balance)];
const colors = [{ positive: '#2490EF', negative: '#B7BFC6' }]; const colors = [
{ positive: uicolors.blue['500'], negative: uicolors.pink['500'] },
];
const format = (value) => fyo.format(value ?? 0, 'Currency'); const format = (value) => fyo.format(value ?? 0, 'Currency');
const yMax = getYMax(points); const yMax = getYMax(points);
const yMin = getYMin(points); const yMin = getYMin(points);

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="flex items-baseline justify-between"> <div class="flex items-baseline justify-between">
<span class="font-medium"><slot name="title"></slot></span> <span class="font-medium text-base"><slot name="title"></slot></span>
<slot name="action"></slot> <slot name="action"></slot>
</div> </div>
</template> </template>

View File

@ -1,8 +1,9 @@
<template> <template>
<div class="flex justify-between gap-8"> <div class="flex">
<div <div
class="flex-col justify-between flex-1"
v-for="(invoice, i) in invoices" v-for="(invoice, i) in invoices"
class="flex-col justify-between w-full p-4"
:class="i === 0 ? 'border-r' : ''"
:key="invoice.title" :key="invoice.title"
> >
<!-- Title and Period Selector --> <!-- Title and Period Selector -->
@ -26,9 +27,9 @@
</SectionHeader> </SectionHeader>
<!-- Widget Body --> <!-- Widget Body -->
<div> <div class="mt-4">
<!-- Paid & Unpaid Amounts --> <!-- Paid & Unpaid Amounts -->
<div class="mt-6 flex justify-between"> <div class="flex justify-between">
<!-- Paid --> <!-- Paid -->
<div <div
class="text-sm bold" class="text-sm bold"
@ -63,6 +64,8 @@
:class=" :class="
invoice.count && invoice.color == 'blue' invoice.count && invoice.color == 'blue'
? 'bg-blue-200' ? 'bg-blue-200'
: invoice.hasData
? 'bg-pink-200'
: 'bg-gray-200' : 'bg-gray-200'
" "
></div> ></div>
@ -71,7 +74,9 @@
:class=" :class="
invoice.count && invoice.color == 'blue' invoice.count && invoice.color == 'blue'
? 'bg-blue-500' ? 'bg-blue-500'
: 'bg-gray-500' : invoice.hasData
? 'bg-pink-500'
: 'bg-gray-400'
" "
:style="`width: ${invoice.barWidth}%`" :style="`width: ${invoice.barWidth}%`"
></div> ></div>
@ -106,6 +111,7 @@ import { ModelNameEnum } from 'models/types';
import Button from 'src/components/Button.vue'; import Button from 'src/components/Button.vue';
import MouseFollower from 'src/components/MouseFollower.vue'; import MouseFollower from 'src/components/MouseFollower.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { uicolors } from 'src/utils/colors';
import { getDatesAndPeriodList } from 'src/utils/misc'; import { getDatesAndPeriodList } from 'src/utils/misc';
import { routeTo } from 'src/utils/ui'; import { routeTo } from 'src/utils/ui';
import PeriodSelector from './PeriodSelector.vue'; import PeriodSelector from './PeriodSelector.vue';
@ -121,7 +127,7 @@ export default {
}, },
data: () => ({ data: () => ({
idx: -1, idx: -1,
colors: ['#33A1FF', '#B7BFC6'], colors: [uicolors.blue['400'], uicolors.pink['400']],
invoices: [ invoices: [
{ {
title: t`Sales Invoices`, title: t`Sales Invoices`,

View File

@ -15,12 +15,19 @@
> >
</PageHeader> </PageHeader>
<div <div class="flex text-base w-full flex-col" v-if="!complete">
class="flex px-4 mt-2 text-base w-full flex-col gap-8"
v-if="!complete"
>
<!-- Type selector --> <!-- Type selector -->
<div class="flex flex-row justify-start items-center w-full gap-2"> <div
class="
flex flex-row
justify-start
items-center
w-full
gap-2
border-b
p-4
"
>
<FormControl <FormControl
:df="importableDf" :df="importableDf"
input-class="bg-transparent text-gray-900 text-base" input-class="bg-transparent text-gray-900 text-base"
@ -45,9 +52,9 @@
</div> </div>
<!-- Settings --> <!-- Settings -->
<div v-if="fileName" class=""> <div v-if="fileName" class="border-b p-4">
<h2 class="text-lg font-semibold">{{ t`Importer Settings` }}</h2> <h2 class="text-lg font-semibold">{{ t`Importer Settings` }}</h2>
<div class="mt-4 flex gap-2"> <div class="mt-2 flex gap-2">
<div <div
v-if="file && isSubmittable" v-if="file && isSubmittable"
class=" class="
@ -124,11 +131,14 @@
</div> </div>
<!-- Label Assigner --> <!-- Label Assigner -->
<div v-if="fileName" class="pb-4"> <div v-if="fileName" class="p-4 border-b">
<h2 class="text-lg font-semibold">{{ t`Assign Imported Labels` }}</h2> <div class="flex items-center gap-2">
<div <h2 class="text-lg font-semibold">{{ t`Assign Imported Labels` }}</h2>
class="gap-2 mt-4 grid grid-flow-col overflow-x-auto no-scrollbar" <p class="text-red-400 text-sm" v-if="isRequiredUnassigned">
> {{ t`* required fields` }}
</p>
</div>
<div class="gap-2 mt-4 grid grid-flow-col overflow-x-auto no-scrollbar">
<div <div
v-for="(f, k) in importer.assignableLabels" v-for="(f, k) in importer.assignableLabels"
:key="'assigner-' + f + '-' + k" :key="'assigner-' + f + '-' + k"
@ -151,24 +161,24 @@
/> />
</div> </div>
</div> </div>
<p
class="text-red-400 text-sm mt-1 -mb-1 p-0 h-0"
v-if="isRequiredUnassigned"
>
{{ t`* required fields` }}
</p>
</div> </div>
<!-- Data Verifier --> <!-- Data Verifier -->
<div v-if="fileName"> <div v-if="fileName">
<h2 class="-mt-4 text-lg font-semibold pb-1"> <div class="overflow-auto border-b">
{{ t`Verify Imported Data` }}
</h2>
<div class="overflow-auto mt-4 pb-4">
<!-- Column Name Rows --> <!-- Column Name Rows -->
<div <div
class="grid grid-flow-col pb-4 border-b gap-2 sticky top-0 bg-white" class="
grid grid-flow-col
border-b
gap-2
sticky
top-0
bg-white
px-4
h-row-mid
items-center
"
style="width: fit-content" style="width: fit-content"
v-if="importer.columnLabels.length > 0" v-if="importer.columnLabels.length > 0"
> >
@ -190,10 +200,17 @@
<!-- Data Rows --> <!-- Data Rows -->
<div <div
v-if="importer.columnLabels.length > 0" v-if="importer.columnLabels.length > 0"
style="max-height: 400px" style="max-height: 500px"
> >
<div <div
class="grid grid-flow-col mt-4 pb-4 border-b gap-2 items-center" class="
grid grid-flow-col
border-b
gap-2
items-center
px-4
h-row-mid
"
style="width: fit-content" style="width: fit-content"
v-for="(r, i) in assignedMatrix" v-for="(r, i) in assignedMatrix"
:key="'matrix-row-' + i" :key="'matrix-row-' + i"
@ -238,13 +255,18 @@
:value="c" :value="c"
/> />
</div> </div>
<!-- Add Row button -->
<button <button
class=" class="
text-gray-600 text-gray-600
hover:text-gray-900 hover:bg-gray-50
flex flex-row flex flex-row
w-full w-full
mt-4 px-4
h-row-mid
border-b
items-center
outline-none outline-none
" "
@click=" @click="

View File

@ -1,17 +1,17 @@
<template> <template>
<div <div
class="py-10 flex-1 bg-white flex justify-center items-center" class="flex-1 flex justify-center items-center bg-gray-25"
:class="{ :class="{
'pointer-events-none': loadingDatabase, 'pointer-events-none': loadingDatabase,
'window-drag': platform !== 'Windows', 'window-drag': platform !== 'Windows',
}" }"
> >
<div <div
class="w-full w-form shadow rounded-lg border relative" class="w-full w-form shadow-lg rounded-lg border relative bg-white"
style="height: 700px" style="height: 700px"
> >
<!-- Welcome to Frappe Books --> <!-- Welcome to Frappe Books -->
<div class="px-6 py-10"> <div class="px-4 py-4">
<h1 class="text-2xl font-semibold select-none"> <h1 class="text-2xl font-semibold select-none">
{{ t`Welcome to Frappe Books` }} {{ t`Welcome to Frappe Books` }}
</h1> </h1>
@ -27,8 +27,8 @@
<!-- New File (Blue Icon) --> <!-- New File (Blue Icon) -->
<div <div
@click="newDatabase" @click="newDatabase"
class="px-6 h-18 flex flex-row items-center gap-4 p-2" class="px-4 h-row-largest flex flex-row items-center gap-4 p-2"
:class="creatingDemo ? '' : 'hover:bg-gray-100 cursor-pointer'" :class="creatingDemo ? '' : 'hover:bg-gray-50 cursor-pointer'"
> >
<div class="w-8 h-8 rounded-full bg-blue-500 relative flex-center"> <div class="w-8 h-8 rounded-full bg-blue-500 relative flex-center">
<feather-icon name="plus" class="text-white w-5 h-5" /> <feather-icon name="plus" class="text-white w-5 h-5" />
@ -47,8 +47,8 @@
<!-- Existing File (Green Icon) --> <!-- Existing File (Green Icon) -->
<div <div
@click="existingDatabase" @click="existingDatabase"
class="px-6 h-18 flex flex-row items-center gap-4 p-2" class="px-4 h-row-largest flex flex-row items-center gap-4 p-2"
:class="creatingDemo ? '' : 'hover:bg-gray-100 cursor-pointer'" :class="creatingDemo ? '' : 'hover:bg-gray-50 cursor-pointer'"
> >
<div class="w-8 h-8 rounded-full bg-green-500 relative flex-center"> <div class="w-8 h-8 rounded-full bg-green-500 relative flex-center">
<feather-icon name="upload" class="w-4 h-4 text-white" /> <feather-icon name="upload" class="w-4 h-4 text-white" />
@ -67,8 +67,8 @@
<!-- File List --> <!-- File List -->
<div class="overflow-y-auto" style="max-height: 340px"> <div class="overflow-y-auto" style="max-height: 340px">
<div <div
class="h-18 px-6 flex gap-4 items-center" class="h-row-largest px-4 flex gap-4 items-center"
:class="creatingDemo ? '' : 'hover:bg-gray-100 cursor-pointer'" :class="creatingDemo ? '' : 'hover:bg-gray-50 cursor-pointer'"
v-for="(file, i) in files" v-for="(file, i) in files"
:key="file.dbPath" :key="file.dbPath"
@click="selectFile(file)" @click="selectFile(file)"
@ -137,8 +137,7 @@
justify-between justify-between
items-center items-center
absolute absolute
px-6 p-4
py-6
text-gray-900 text-gray-900
" "
style="top: 100%; transform: translateY(-100%)" style="top: 100%; transform: translateY(-100%)"

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="flex overflow-hidden"> <div class="flex overflow-hidden">
<Sidebar <Sidebar
class="w-sidebar flex-shrink-0" class="w-sidebar flex-shrink-0 border-r"
@change-db-file="$emit('change-db-file')" @change-db-file="$emit('change-db-file')"
/> />
<div class="flex flex-1 overflow-y-hidden bg-white"> <div class="flex flex-1 overflow-y-hidden bg-white">

View File

@ -1,26 +1,21 @@
<template> <template>
<div class="flex flex-col overflow-y-hidden"> <div class="flex flex-col overflow-y-hidden">
<PageHeader :title="t`Setup Your Workspace`" /> <PageHeader :title="t`Setup Your Workspace`" />
<div class="flex-1 mx-4 overflow-y-auto overflow-x-hidden"> <div class="flex-1 overflow-y-auto overflow-x-hidden">
<div class="my-4" v-for="section in sections" :key="section.label"> <div
class="p-4 border-b"
v-for="section in sections"
:key="section.label"
>
<h2 class="font-medium">{{ section.label }}</h2> <h2 class="font-medium">{{ section.label }}</h2>
<div class="flex mt-4 -mx-2"> <div class="flex mt-4 gap-4">
<div <div
class="flex-shrink-0 w-full px-2 md:w-1/3 sm:w-1/2" class="w-full md:w-1/3 sm:w-1/2"
v-for="item in section.items" v-for="item in section.items"
:key="item.label" :key="item.label"
> >
<div <div
class=" class="flex flex-col justify-between h-40 p-4 border rounded-lg"
flex flex-col
justify-between
h-40
p-4
border
rounded-lg
cursor-pointer
hover:shadow-md
"
@mouseenter="() => (activeCard = item.key)" @mouseenter="() => (activeCard = item.key)"
@mouseleave="() => (activeCard = null)" @mouseleave="() => (activeCard = null)"
> >

View File

@ -1,11 +1,10 @@
<template> <template>
<div class="flex flex-col" v-if="doc"> <FormContainer :backLink="true">
<!-- Page Header (Title, Buttons, etc) --> <!-- Page Header (Title, Buttons, etc) -->
<PageHeader :backLink="true"> <template #header v-if="doc">
<StatusBadge :status="status" /> <StatusBadge :status="status" />
<Button <Button
v-if="doc?.submitted" v-if="doc?.submitted"
class="text-gray-900 text-xs"
:icon="true" :icon="true"
@click="routeTo(`/print/${doc.schemaName}/${doc.name}`)" @click="routeTo(`/print/${doc.schemaName}/${doc.name}`)"
> >
@ -15,7 +14,6 @@
<Button <Button
v-if="doc?.notInserted || doc?.dirty" v-if="doc?.notInserted || doc?.dirty"
type="primary" type="primary"
class="text-white text-xs"
@click="sync" @click="sync"
> >
{{ t`Save` }} {{ t`Save` }}
@ -23,28 +21,24 @@
<Button <Button
v-if="!doc?.dirty && !doc?.notInserted && !doc?.submitted" v-if="!doc?.dirty && !doc?.notInserted && !doc?.submitted"
type="primary" type="primary"
class="text-white text-xs"
@click="submit" @click="submit"
>{{ t`Submit` }}</Button >{{ t`Submit` }}</Button
> >
</PageHeader> </template>
<!-- Invoice Form --> <!-- Invoice Form -->
<div <template #body v-if="doc">
class=" <div
border class="
rounded-lg px-4
shadow text-xl
h-full font-semibold
flex flex-col flex
mt-2 justify-between
self-center h-row-large
w-form items-center
h-form "
" >
v-if="doc"
>
<div class="p-4 text-2xl font-semibold flex justify-between">
<h1> <h1>
{{ doc.notInserted ? t`New Entry` : doc.name }} {{ doc.notInserted ? t`New Entry` : doc.name }}
</h1> </h1>
@ -115,7 +109,7 @@
<div v-if="doc.items?.length ?? 0" class="mt-auto"> <div v-if="doc.items?.length ?? 0" class="mt-auto">
<hr /> <hr />
<div class="flex justify-between text-base m-6 gap-12"> <div class="flex justify-between text-base m-4 gap-12">
<!-- Form Terms--> <!-- Form Terms-->
<FormControl <FormControl
class="w-1/2 self-end" class="w-1/2 self-end"
@ -180,8 +174,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> </template>
</div> </FormContainer>
</template> </template>
<script> <script>
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
@ -191,7 +185,7 @@ import Button from 'src/components/Button.vue';
import FormControl from 'src/components/Controls/FormControl.vue'; import FormControl from 'src/components/Controls/FormControl.vue';
import Table from 'src/components/Controls/Table.vue'; import Table from 'src/components/Controls/Table.vue';
import DropdownWithActions from 'src/components/DropdownWithActions.vue'; import DropdownWithActions from 'src/components/DropdownWithActions.vue';
import PageHeader from 'src/components/PageHeader.vue'; import FormContainer from 'src/components/FormContainer.vue';
import StatusBadge from 'src/components/StatusBadge.vue'; import StatusBadge from 'src/components/StatusBadge.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { import {
@ -206,12 +200,12 @@ export default {
name: 'InvoiceForm', name: 'InvoiceForm',
props: { schemaName: String, name: String }, props: { schemaName: String, name: String },
components: { components: {
PageHeader,
StatusBadge, StatusBadge,
Button, Button,
FormControl, FormControl,
DropdownWithActions, DropdownWithActions,
Table, Table,
FormContainer,
}, },
provide() { provide() {
return { return {
@ -245,9 +239,7 @@ export default {
await this.handleError(error); await this.handleError(error);
} }
this.printSettings = await fyo.doc.getDoc('PrintSettings'); this.printSettings = await fyo.doc.getDoc('PrintSettings');
this.companyName = ( this.companyName = (await fyo.doc.getDoc('AccountingSettings')).companyName;
await fyo.doc.getDoc('AccountingSettings')
).companyName;
let query = this.$route.query; let query = this.$route.query;
if (query.values && query.schemaName === this.schemaName) { if (query.values && query.schemaName === this.schemaName) {

View File

@ -1,44 +1,30 @@
<template> <template>
<div class="flex flex-col"> <FormContainer :backLink="true">
<!-- Page Header (Title, Buttons, etc) --> <!-- Page Header (Title, Buttons, etc) -->
<PageHeader :backLink="true"> <template #header v-if="doc">
<template v-if="doc"> <StatusBadge :status="status" />
<StatusBadge :status="status" /> <DropdownWithActions :actions="actions" />
<DropdownWithActions :actions="actions" /> <Button
<Button v-if="doc?.notInserted || doc?.dirty"
v-if="doc?.notInserted || doc?.dirty" type="primary"
type="primary" class="text-white text-xs"
class="text-white text-xs" @click="sync"
@click="sync" >
> {{ t`Save` }}
{{ t`Save` }} </Button>
</Button> <Button
<Button v-else-if="!doc.dirty && !doc.notInserted && !doc.submitted"
v-else-if="!doc.dirty && !doc.notInserted && !doc.submitted" type="primary"
type="primary" class="text-white text-xs"
class="text-white text-xs" @click="submit"
@click="submit" >
> {{ t`Submit` }}
{{ t`Submit` }} </Button>
</Button> </template>
</template>
</PageHeader>
<!-- Journal Entry Form --> <!-- Journal Entry Form -->
<div <template #body v-if="doc">
class=" <div class="px-4 text-xl font-semibold flex justify-between h-row-large items-center">
self-center
border
rounded-lg
shadow
flex flex-col
mt-2
w-form
h-form
"
v-if="doc"
>
<div class="p-4 text-2xl font-semibold flex justify-between">
<h1> <h1>
{{ doc.notInserted ? t`New Entry` : doc.name }} {{ doc.notInserted ? t`New Entry` : doc.name }}
</h1> </h1>
@ -112,7 +98,7 @@
<!-- Footer --> <!-- Footer -->
<div v-if="doc.accounts?.length ?? 0" class="mt-auto"> <div v-if="doc.accounts?.length ?? 0" class="mt-auto">
<hr /> <hr />
<div class="flex justify-between text-base m-6 gap-12"> <div class="flex justify-between text-base m-4 gap-12">
<!-- User Remark --> <!-- User Remark -->
<FormControl <FormControl
v-if="!doc.submitted || doc.userRemark" v-if="!doc.submitted || doc.userRemark"
@ -139,18 +125,18 @@
</div> </div>
</div> </div>
</div> </div>
</div> </template>
</div> </FormContainer>
</template> </template>
<script> <script>
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import Button from 'src/components/Button'; import Button from 'src/components/Button.vue';
import FormControl from 'src/components/Controls/FormControl.vue'; import FormControl from 'src/components/Controls/FormControl.vue';
import Table from 'src/components/Controls/Table.vue'; import Table from 'src/components/Controls/Table.vue';
import DropdownWithActions from 'src/components/DropdownWithActions'; import DropdownWithActions from 'src/components/DropdownWithActions.vue';
import PageHeader from 'src/components/PageHeader'; import FormContainer from 'src/components/FormContainer.vue';
import StatusBadge from 'src/components/StatusBadge'; import StatusBadge from 'src/components/StatusBadge.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { import {
getActionsForDocument, getActionsForDocument,
@ -163,12 +149,12 @@ export default {
name: 'JournalEntryForm', name: 'JournalEntryForm',
props: ['name'], props: ['name'],
components: { components: {
PageHeader,
Button, Button,
DropdownWithActions, DropdownWithActions,
StatusBadge, StatusBadge,
FormControl, FormControl,
Table, Table,
FormContainer,
}, },
provide() { provide() {
return { return {

View File

@ -1,19 +1,26 @@
<template> <template>
<div class="mx-4 text-base flex flex-col overflow-y-hidden"> <div class="text-base flex flex-col overflow-y-hidden">
<!-- Title Row --> <!-- Title Row -->
<div class="flex items-center"> <div class="flex items-center">
<p class="w-8 text-right mr-4 text-gray-700">#</p> <p class="w-8 text-right mr-4 text-gray-700">#</p>
<Row <Row
class="flex-1 text-gray-700 border-none" class="flex-1 text-gray-700 border-none h-row-mid"
:columnCount="columns.length" :columnCount="columns.length"
gap="1rem" gap="1rem"
> >
<div <div
v-for="(column, i) in columns" v-for="(column, i) in columns"
:key="column.label" :key="column.label"
class="py-4 overflow-x-auto no-scrollbar whitespace-nowrap" class="
overflow-x-auto
no-scrollbar
whitespace-nowrap
h-row
items-center
flex
"
:class="{ :class="{
'text-right': isNumeric(column.fieldtype), 'ml-auto': isNumeric(column.fieldtype),
'pr-4': i === columns.length - 1, 'pr-4': i === columns.length - 1,
}" }"
> >
@ -27,13 +34,13 @@
<div class="overflow-y-auto" v-if="dataSlice.length !== 0"> <div class="overflow-y-auto" v-if="dataSlice.length !== 0">
<div v-for="(doc, i) in dataSlice" :key="doc.name"> <div v-for="(doc, i) in dataSlice" :key="doc.name">
<!-- Row Content --> <!-- Row Content -->
<div class="flex hover:bg-gray-100 items-center"> <div class="flex hover:bg-gray-50 items-center">
<p class="w-8 text-right mr-4 text-gray-900"> <p class="w-8 text-right mr-4 text-gray-900">
{{ i + pageStart + 1 }} {{ i + pageStart + 1 }}
</p> </p>
<Row <Row
gap="1rem" gap="1rem"
class="cursor-pointer text-gray-900 flex-1 border-none" class="cursor-pointer text-gray-900 flex-1 border-none h-row-mid"
@click="openForm(doc)" @click="openForm(doc)"
:columnCount="columns.length" :columnCount="columns.length"
> >
@ -49,14 +56,18 @@
/> />
</Row> </Row>
</div> </div>
<hr v-if="i !== dataSlice.length - 1" /> <hr v-if="!(i === dataSlice.length - 1 && i > 13)" />
</div> </div>
</div> </div>
<!-- Pagination Footer --> <!-- Pagination Footer -->
<div class="mt-auto" v-if="data?.length"> <div class="mt-auto" v-if="data?.length">
<hr /> <hr />
<Paginator :item-count="data.length" @index-change="setPageIndices" /> <Paginator
:item-count="data.length"
@index-change="setPageIndices"
class="px-4"
/>
</div> </div>
<!-- Empty State --> <!-- Empty State -->

View File

@ -1,11 +1,12 @@
<template> <template>
<div class="py-4 flex items-center truncate" :class="cellClass"> <div class="flex items-center truncate" :class="cellClass">
<span class="truncate" v-if="!customRenderer">{{ columnValue }}</span> <span class="truncate" v-if="!customRenderer">{{ columnValue }}</span>
<component v-else :is="customRenderer" /> <component v-else :is="customRenderer" />
</div> </div>
</template> </template>
<script> <script>
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { isNumeric } from 'src/utils';
export default { export default {
name: 'ListCell', name: 'ListCell',
@ -21,9 +22,7 @@ export default {
return this.column.render(this.doc); return this.column.render(this.doc);
}, },
cellClass() { cellClass() {
return ['Int', 'Float', 'Currency'].includes(this.column.fieldtype) return isNumeric(this.column.fieldtype) ? 'justify-end' : '';
? 'justify-end'
: '';
}, },
}, },
}; };

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="flex"> <div class="flex">
<div class="flex flex-col flex-1"> <div class="flex flex-col flex-1 bg-gray-25">
<PageHeader :backLink="true" class="bg-white z-10"> <PageHeader :backLink="true" class="z-10" :border="false">
<Button <Button
class="text-gray-900 text-xs" class="text-gray-900 text-xs"
@click="showCustomiser = !showCustomiser" @click="showCustomiser = !showCustomiser"
@ -16,15 +16,14 @@
<!-- Printview Preview --> <!-- Printview Preview -->
<div <div
v-if="doc && printSettings" v-if="doc && printSettings"
class="flex justify-center flex-1 -mt-36 overflow-auto relative" class="flex justify-center flex-1 overflow-auto relative"
> >
<div <div
class="h-full shadow-lg mb-12 absolute" class="h-full shadow mb-4 absolute bg-white"
style=" style="
width: 21cm; width: 21cm;
min-height: 29.7cm; height: 29.7cm;
height: max-content; transform: scale(0.65) translateY(-300px);
transform: scale(0.7);
" "
ref="printContainer" ref="printContainer"
> >
@ -39,13 +38,19 @@
<!-- Printview Customizer --> <!-- Printview Customizer -->
<div class="border-l w-80" v-if="showCustomiser"> <div class="border-l w-80" v-if="showCustomiser">
<div class="mt-4 px-4 flex items-center justify-between"> <div
class="px-4 flex items-center justify-between h-row-largest border-b"
>
<h2 class="font-semibold">{{ t`Customise` }}</h2> <h2 class="font-semibold">{{ t`Customise` }}</h2>
<Button :icon="true" @click="showCustomiser = false"> <Button :icon="true" @click="showCustomiser = false">
<feather-icon name="x" class="w-4 h-4" /> <feather-icon name="x" class="w-4 h-4" />
</Button> </Button>
</div> </div>
<TwoColumnForm class="mt-4" :doc="printSettings" :autosave="true" /> <TwoColumnForm
:doc="printSettings"
:autosave="true"
class="border-none"
/>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,7 +1,10 @@
<template> <template>
<div class="border-l h-full overflow-auto"> <div
class="border-l h-full overflow-auto"
:class="white ? 'bg-white' : 'bg-gray-25'"
>
<!-- Quick edit Tool bar --> <!-- Quick edit Tool bar -->
<div class="flex items-center justify-between px-4 pt-4"> <div class="flex items-center justify-between px-4 border-b h-row-largest">
<!-- Close Button and Status Text --> <!-- Close Button and Status Text -->
<div class="flex items-center"> <div class="flex items-center">
<Button :icon="true" @click="routeToPrevious"> <Button :icon="true" @click="routeToPrevious">
@ -43,7 +46,11 @@
</div> </div>
<!-- Name and image --> <!-- Name and image -->
<div class="p-4 gap-2 flex-center flex flex-col items-center" v-if="doc"> <div
class="px-4 flex-center flex flex-col items-center gap-1.5"
style="height: calc(var(--h-row-mid) * 2 + 1px)"
v-if="doc"
>
<FormControl <FormControl
v-if="imageField" v-if="imageField"
:df="imageField" :df="imageField"
@ -53,7 +60,7 @@
:letter-placeholder="doc[titleField.fieldname]?.[0] ?? null" :letter-placeholder="doc[titleField.fieldname]?.[0] ?? null"
/> />
<FormControl <FormControl
input-class="text-center" input-class="text-center h-8 bg-transparent"
ref="titleControl" ref="titleControl"
v-if="titleField" v-if="titleField"
:df="titleField" :df="titleField"
@ -97,6 +104,7 @@ export default {
name: String, name: String,
schemaName: String, schemaName: String,
defaults: String, defaults: String,
white: { type: Boolean, default: false },
hideFields: { type: Array, default: () => [] }, hideFields: { type: Array, default: () => [] },
showFields: { type: Array, default: () => [] }, showFields: { type: Array, default: () => [] },
}, },

View File

@ -3,6 +3,7 @@
<PageHeader :title="title"> <PageHeader :title="title">
<DropdownWithActions <DropdownWithActions
v-for="group of groupedActions" v-for="group of groupedActions"
:icon="false"
:key="group.label" :key="group.label"
:type="group.type" :type="group.type"
:actions="group.actions" :actions="group.actions"
@ -13,7 +14,7 @@
</PageHeader> </PageHeader>
<!-- Filters --> <!-- Filters -->
<div v-if="report" class="mx-4 grid grid-cols-5 gap-2"> <div v-if="report" class="grid grid-cols-5 gap-2 p-4 border-b">
<FormControl <FormControl
v-for="field in report.filters" v-for="field in report.filters"
size="small" size="small"
@ -30,7 +31,7 @@
</div> </div>
<!-- Report Body --> <!-- Report Body -->
<ListReport v-if="report" :report="report" class="mx-4 mt-4" /> <ListReport v-if="report" :report="report" class="" />
</div> </div>
</template> </template>
<script> <script>

View File

@ -1,22 +1,8 @@
<template> <template>
<div class="flex flex-col overflow-hidden"> <FormContainer :title="t`Settings`">
<PageHeader :title="t`Settings`" /> <template #body>
<div
class="
border
rounded-lg
shadow
h-full
flex flex-col
justify-between
self-center
mt-2
w-form
h-form
"
>
<!-- Icon Tab Bar --> <!-- Icon Tab Bar -->
<div class="flex justify-around mb-4 mt-6"> <div class="flex justify-around mb-2 mt-4">
<div <div
v-for="(tab, i) in tabs" v-for="(tab, i) in tabs"
:key="tab.label" :key="tab.label"
@ -39,13 +25,14 @@
<div class="flex-1 overflow-y-auto"> <div class="flex-1 overflow-y-auto">
<component :is="activeTabComponent" @change="handleChange" /> <component :is="activeTabComponent" @change="handleChange" />
</div> </div>
</div> </template>
</div> </FormContainer>
</template> </template>
<script> <script>
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { t } from 'fyo'; import { t } from 'fyo';
import Button from 'src/components/Button.vue'; import Button from 'src/components/Button.vue';
import FormContainer from 'src/components/FormContainer.vue';
import Icon from 'src/components/Icon.vue'; import Icon from 'src/components/Icon.vue';
import PageHeader from 'src/components/PageHeader.vue'; import PageHeader from 'src/components/PageHeader.vue';
import Row from 'src/components/Row.vue'; import Row from 'src/components/Row.vue';
@ -64,6 +51,7 @@ export default {
StatusBadge, StatusBadge,
Button, Button,
Row, Row,
FormContainer,
}, },
data() { data() {
return { return {

View File

@ -61,9 +61,7 @@ export default {
}, },
async mounted() { async mounted() {
this.doc = await fyo.doc.getDoc('PrintSettings'); this.doc = await fyo.doc.getDoc('PrintSettings');
this.companyName = ( this.companyName = (await fyo.doc.getDoc('AccountingSettings')).companyName;
await fyo.doc.getDoc('AccountingSettings')
).companyName;
}, },
computed: { computed: {
fields() { fields() {

View File

@ -8,10 +8,15 @@
:emit-change="true" :emit-change="true"
@change="forwardChangeEvent" @change="forwardChangeEvent"
/> />
<LanguageSelector <div class="flex p-4 justify-between">
class="text-sm w-28 bg-gray-100 rounded-md mb-6 ml-6" <LanguageSelector
input-class="py-1.5 bg-transparent" class="text-sm w-28 bg-gray-100 rounded-md"
/> input-class="py-1.5 bg-transparent"
/>
<p class="mt-auto text-gray-600 text-base select-none">
{{ `v${fyo.store.appVersion}` }}
</p>
</div>
</div> </div>
</template> </template>

View File

@ -1,7 +1,5 @@
<template> <template>
<div <div class="flex-1 bg-gray-25 flex justify-center items-center window-drag">
class="py-10 flex-1 bg-white flex justify-center items-center window-drag"
>
<!-- 0: Language Selection Slide --> <!-- 0: Language Selection Slide -->
<Slide <Slide
@primary-clicked="handlePrimary" @primary-clicked="handlePrimary"

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="w-form shadow rounded-lg border relative" style="height: 700px"> <div class="w-form shadow-lg rounded-lg border relative bg-white" style="height: 700px">
<!-- Slide Title --> <!-- Slide Title -->
<div class="px-6 py-10"> <div class="p-4">
<h1 class="text-2xl font-semibold select-none"> <h1 class="text-2xl font-semibold select-none">
<slot name="title"></slot> <slot name="title"></slot>
</h1> </h1>
@ -15,7 +15,7 @@
<!-- Slide Buttons --> <!-- Slide Buttons -->
<div <div
class="flex justify-between px-6 pb-6 window-no-drag absolute w-form" class="flex justify-between px-4 pb-4 window-no-drag absolute w-form"
style="top: 100%; transform: translateY(-100%)" style="top: 100%; transform: translateY(-100%)"
> >
<Button <Button

View File

@ -53,6 +53,22 @@ html {
display: none; display: none;
} }
:root {
--w-app: 1200px;
--w-sidebar: 12rem;
--w-desk: calc(100vw - var(--w-sidebar));
--w-desk-fixed: calc(var(--w-app) - var(--w-sidebar));
--w-scrollbar: 0.5rem;
/* Row Heights */
--h-row-smallest: 2rem;
--h-row-small: 2.5rem;
--h-row-mid: 3rem;
--h-row-large: 3.5rem;
--h-row-largest: 4rem;
--h-app: 800px;
}
.w-form { .w-form {
width: 600px; width: 600px;
} }
@ -61,10 +77,30 @@ html {
height: 800px; height: 800px;
} }
.h-row-smallest {
height: var(--h-row-smallest);
}
.h-row-small {
height: var(--h-row-small);
}
.h-row-mid {
height: var(--h-row-mid);
}
.h-row-large {
height: var(--h-row-large);
}
.h-row-largest {
height: var(--h-row-largest);
}
.w-sidebar { .w-sidebar {
width: 12rem; width: var(--w-sidebar);
} }
.w-desk { .w-desk {
width: calc(100vw - 12rem); width: var(--w-desk);
} }

View File

@ -1,4 +0,0 @@
import resolveConfig from 'tailwindcss/resolveConfig';
import tailwindConfig from '../tailwind.config';
export default resolveConfig(tailwindConfig).theme;

View File

@ -1,3 +1,7 @@
import { theme } from '../../tailwind.config';
export const uicolors = theme.extend.colors;
export const indicators = { export const indicators = {
GRAY: 'grey', GRAY: 'grey',
GREY: 'grey', GREY: 'grey',
@ -34,7 +38,8 @@ const getValidColor = (color: string) => {
}; };
export function getBgColorClass(color: string) { export function getBgColorClass(color: string) {
return `bg-${getValidColor(color)}-100`; const vcolor = getValidColor(color);
return `bg-${vcolor}-100`;
} }
export function getColorClass(color: string, type: 'bg' | 'text', value = 300) { export function getColorClass(color: string, type: 'bg' | 'text', value = 300) {

View File

@ -57,19 +57,19 @@ module.exports = {
'span-full': '1 / -1', 'span-full': '1 / -1',
}, },
colors: { colors: {
brand: '#2490EF', black: '#1E293B',
'brand-100': '#f4f9ff',
black: '#112B42',
gray: { gray: {
100: '#f4f4f6', 25: '#fcfcfd',
200: '#e9ebed', 50: '#f8f9fc',
300: '#dfe1e2', 100: '#f2f4f8',
400: '#cccfd1', 200: '#ebeff5',
500: '#b7bfc6', 300: '#e2e8f0',
600: '#a1abb4', 400: '#cad5e2',
700: '#9fa5a8', 500: '#9aa8bc',
800: '#7f878a', 600: '#8493a9',
900: '#415668', 700: '#64748b',
800: '#475569',
900: '#334155',
}, },
red: { red: {
100: '#fff5f5', 100: '#fff5f5',
@ -132,7 +132,7 @@ module.exports = {
300: '#99d0ff', 300: '#99d0ff',
400: '#66b8ff', 400: '#66b8ff',
500: '#33a1ff', 500: '#33a1ff',
600: '#0089ff', 600: '#2490ef',
700: '#006ecc', 700: '#006ecc',
800: '#005299', 800: '#005299',
900: '#003766', 900: '#003766',
@ -160,15 +160,15 @@ module.exports = {
900: '#44337a', 900: '#44337a',
}, },
pink: { pink: {
100: '#fff5f7', 100: '#fdf7f8',
200: '#fed7e2', 200: '#fbeef1',
300: '#fbb6ce', 300: '#f7dee5',
400: '#f687b3', 400: '#eec3d2',
500: '#ed64a6', 500: '#df9eb8',
600: '#d53f8c', 600: '#cf82a7',
700: '#b83280', 700: '#ac688b',
800: '#97266d', 800: '#8f5b79',
900: '#702459', 900: '#70485f',
}, },
}, },
}, },