@likable-hair/svelte 3.0.19 → 3.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/composed/forms/Dropdown.svelte +16 -7
- package/dist/components/composed/forms/Dropdown.svelte.d.ts +4 -0
- package/dist/components/composed/list/PaginatedTable.svelte +131 -133
- package/dist/components/composed/list/PaginatedTable.svelte.d.ts +68 -2
- package/dist/components/composed/list/Paginator.svelte +12 -6
- package/dist/components/composed/search/Filters.css +0 -0
- package/dist/components/composed/search/Filters.svelte +97 -0
- package/dist/components/composed/search/Filters.svelte.d.ts +26 -0
- package/dist/components/simple/buttons/Button.css +1 -0
- package/dist/components/simple/buttons/Button.svelte +4 -0
- package/dist/components/simple/forms/Autocomplete.svelte +5 -1
- package/dist/components/simple/forms/Autocomplete.svelte.d.ts +1 -0
- package/dist/components/simple/lists/SimpleTable.svelte +25 -23
- package/dist/components/simple/lists/SimpleTable.svelte.d.ts +3 -1
- package/dist/components/simple/lists/columnTypes.d.ts +35 -0
- package/dist/components/simple/lists/columnTypes.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/utils/filters/builder.d.ts +43 -0
- package/dist/utils/filters/builder.js +137 -0
- package/dist/utils/filters/filters.d.ts +26 -0
- package/dist/utils/filters/filters.js +29 -0
- package/dist/utils/filters/modifiers/join.d.ts +26 -0
- package/dist/utils/filters/modifiers/join.js +1 -0
- package/dist/utils/filters/modifiers/where.d.ts +29 -0
- package/dist/utils/filters/modifiers/where.js +1 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<script>import Autocomplete from "../../../components/simple/forms/Autocomplete.svelte";
|
|
4
4
|
import Button from "../../simple/buttons/Button.svelte";
|
|
5
5
|
import Icon from "../../simple/media/Icon.svelte";
|
|
6
|
-
export let items = [], values = [], multiple = false, searchText = void 0, maxVisibleChips = void 0, placeholder = "Seleziona", icon = void 0;
|
|
6
|
+
export let items = [], values = [], multiple = false, searchText = void 0, maxVisibleChips = void 0, placeholder = "Seleziona", clearable = true, mandatory = true, icon = void 0;
|
|
7
7
|
$:
|
|
8
8
|
generatedLabel = values.length == 1 ? values[0].label : `${values.length} Selezionati`;
|
|
9
9
|
function handleCloseClick(event) {
|
|
@@ -19,11 +19,15 @@ function handleCloseClick(event) {
|
|
|
19
19
|
bind:searchText
|
|
20
20
|
bind:multiple
|
|
21
21
|
bind:maxVisibleChips
|
|
22
|
+
bind:mandatory
|
|
22
23
|
searchFunction={() => true}
|
|
24
|
+
on:change
|
|
23
25
|
>
|
|
24
26
|
<svelte:fragment slot="selection-container" let:openMenu let:handleKeyDown>
|
|
25
27
|
<Button
|
|
26
28
|
--button-default-background-color="transparent"
|
|
29
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-400), .3)"
|
|
30
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
27
31
|
--button-default-border="2px solid rgb(var(--global-color-primary-400))"
|
|
28
32
|
--button-default-color="rgb(var(--global-color-contrast-800))"
|
|
29
33
|
on:click={openMenu}
|
|
@@ -48,11 +52,13 @@ function handleCloseClick(event) {
|
|
|
48
52
|
{:else}
|
|
49
53
|
<div class="space-between">
|
|
50
54
|
<div>{generatedLabel}</div>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
{#if clearable}
|
|
56
|
+
<Icon
|
|
57
|
+
name="mdi-close"
|
|
58
|
+
click
|
|
59
|
+
on:click={handleCloseClick}
|
|
60
|
+
></Icon>
|
|
61
|
+
{/if}
|
|
56
62
|
</div>
|
|
57
63
|
{/if}
|
|
58
64
|
</div>
|
|
@@ -67,7 +73,9 @@ function handleCloseClick(event) {
|
|
|
67
73
|
justify-content: flex-start;
|
|
68
74
|
align-items: center;
|
|
69
75
|
gap: 10px;
|
|
70
|
-
width:
|
|
76
|
+
width: 100%;
|
|
77
|
+
text-overflow: ellipsis;
|
|
78
|
+
white-space: pre;
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
.space-between {
|
|
@@ -75,5 +83,6 @@ function handleCloseClick(event) {
|
|
|
75
83
|
display: flex;
|
|
76
84
|
justify-content: space-between;
|
|
77
85
|
align-items: center;
|
|
86
|
+
gap: 10px;
|
|
78
87
|
}
|
|
79
88
|
</style>
|
|
@@ -9,9 +9,13 @@ declare const __propDef: {
|
|
|
9
9
|
searchText?: string | undefined;
|
|
10
10
|
maxVisibleChips?: number | undefined;
|
|
11
11
|
placeholder?: string | undefined;
|
|
12
|
+
clearable?: boolean | undefined;
|
|
13
|
+
mandatory?: boolean | undefined;
|
|
12
14
|
icon?: string | undefined;
|
|
13
15
|
};
|
|
14
16
|
events: {
|
|
17
|
+
change: CustomEvent<any>;
|
|
18
|
+
} & {
|
|
15
19
|
[evt: string]: CustomEvent<any>;
|
|
16
20
|
};
|
|
17
21
|
slots: {
|
|
@@ -1,152 +1,150 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
width?: string;
|
|
7
|
-
minWidth?: string;
|
|
8
|
-
data?: { [key: string]: any };
|
|
9
|
-
};
|
|
1
|
+
<script context="module">import SimpleTable from "../../simple/lists/SimpleTable.svelte";
|
|
2
|
+
import Icon from "../../simple/media/Icon.svelte";
|
|
3
|
+
import Paginator from "./Paginator.svelte";
|
|
4
|
+
import Dropdown from "../forms/Dropdown.svelte";
|
|
5
|
+
import { createEventDispatcher } from "svelte";
|
|
10
6
|
</script>
|
|
11
7
|
|
|
12
|
-
<script
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
let items: { [key: string]: any }[] = [],
|
|
39
|
-
maxPage: number | undefined = undefined
|
|
40
|
-
|
|
41
|
-
onMount(() => {
|
|
42
|
-
loadRows()
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
async function loadRows() {
|
|
46
|
-
if(!!fetcher) {
|
|
47
|
-
loading = true
|
|
48
|
-
let results = await fetcher({page, perPage, filters})
|
|
49
|
-
|
|
50
|
-
items = results.data
|
|
51
|
-
page = results.meta.currentPage
|
|
52
|
-
maxPage = results.meta.lastPage
|
|
53
|
-
loading = false
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function handlePaginationChange() {
|
|
58
|
-
loadRows()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function handlePerPageChange() {
|
|
62
|
-
page = 1
|
|
63
|
-
loadRows()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
$: perPageOptionsFormatted = perPageOptions.map((el) => {
|
|
67
|
-
return {
|
|
68
|
-
value: el,
|
|
69
|
-
text: el.toString()
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
$: if(reload) {
|
|
73
|
-
loadRows().then(() => {
|
|
74
|
-
reload = false
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
$: filters && loadRows()
|
|
79
|
-
|
|
8
|
+
<script>let clazz = {};
|
|
9
|
+
export { clazz as class };
|
|
10
|
+
export let headers = [], items = [], sortedBy = void 0, sortDirection = void 0, page = 1, maxPage = void 0, rowsPerPageOptions = [
|
|
11
|
+
{ label: "20", value: 20 },
|
|
12
|
+
{ label: "50", value: 50 },
|
|
13
|
+
{ label: "100", value: 100 }
|
|
14
|
+
], hideRowsPerPage = false, totalElements = void 0, rowsPerPage = 20;
|
|
15
|
+
let dispatch = createEventDispatcher();
|
|
16
|
+
let rowsPerPageSelection = [];
|
|
17
|
+
$:
|
|
18
|
+
rowsPerPageSelection = [
|
|
19
|
+
{ label: rowsPerPage.toString(), value: rowsPerPage }
|
|
20
|
+
];
|
|
21
|
+
$:
|
|
22
|
+
if (totalElements !== void 0)
|
|
23
|
+
maxPage = Math.max(Math.round(totalElements / rowsPerPage), 1);
|
|
24
|
+
function handleRowsPerPageChange(e) {
|
|
25
|
+
rowsPerPage = Number(e.detail.selection?.[0].value);
|
|
26
|
+
handlePaginationChange();
|
|
27
|
+
}
|
|
28
|
+
function handlePaginationChange() {
|
|
29
|
+
dispatch("paginationChange", {
|
|
30
|
+
rowsPerPage,
|
|
31
|
+
page
|
|
32
|
+
});
|
|
33
|
+
}
|
|
80
34
|
</script>
|
|
81
35
|
|
|
82
|
-
<div class="
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
36
|
+
<div class="paginated-table">
|
|
37
|
+
<SimpleTable
|
|
38
|
+
bind:headers
|
|
39
|
+
bind:class={clazz.simpleTable}
|
|
40
|
+
bind:items
|
|
41
|
+
bind:sortedBy
|
|
42
|
+
bind:sortDirection
|
|
43
|
+
on:sort
|
|
90
44
|
>
|
|
91
|
-
<svelte:fragment slot="
|
|
92
|
-
<slot name="
|
|
45
|
+
<svelte:fragment slot="header" let:head>
|
|
46
|
+
<slot name="header" {head} >
|
|
47
|
+
<span class="header-label">
|
|
48
|
+
<slot name="headerLabel">
|
|
49
|
+
{head.label}
|
|
50
|
+
</slot>
|
|
51
|
+
</span>
|
|
52
|
+
{#if head.sortable}
|
|
53
|
+
<span
|
|
54
|
+
class="header-sort-icon"
|
|
55
|
+
class:active={sortedBy == head.value}
|
|
56
|
+
class:asc={sortDirection == 'asc'}
|
|
57
|
+
class:desc={sortDirection == 'desc'}
|
|
58
|
+
>
|
|
59
|
+
{#if sortDirection == 'asc'}
|
|
60
|
+
<Icon name="mdi-arrow-up"></Icon>
|
|
61
|
+
{:else}
|
|
62
|
+
<Icon name="mdi-arrow-down"></Icon>
|
|
63
|
+
{/if}
|
|
64
|
+
</span>
|
|
65
|
+
{/if}
|
|
66
|
+
</slot>
|
|
93
67
|
</svelte:fragment>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
68
|
+
<svelte:fragment
|
|
69
|
+
slot="custom"
|
|
70
|
+
let:columnIndex
|
|
71
|
+
let:index
|
|
72
|
+
let:header
|
|
73
|
+
let:item
|
|
74
|
+
>
|
|
75
|
+
<slot name="custom" {index} {columnIndex} {header} {item}/>
|
|
97
76
|
</svelte:fragment>
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
77
|
+
<svelte:fragment slot="rowActions" let:index let:item>
|
|
78
|
+
<slot name="rowActions" {index} {item} />
|
|
79
|
+
</svelte:fragment>
|
|
80
|
+
<svelte:fragment slot="append" let:index let:item>
|
|
81
|
+
<slot name="append" {index} {item} />
|
|
82
|
+
</svelte:fragment>
|
|
83
|
+
</SimpleTable>
|
|
84
|
+
<div class="footer">
|
|
85
|
+
<slot
|
|
86
|
+
name="footer"
|
|
87
|
+
{hideRowsPerPage}
|
|
88
|
+
{rowsPerPageOptions}
|
|
89
|
+
{rowsPerPageSelection}
|
|
90
|
+
{totalElements}
|
|
91
|
+
{page}
|
|
92
|
+
{maxPage}
|
|
93
|
+
{rowsPerPage}
|
|
94
|
+
{handlePaginationChange}
|
|
95
|
+
>
|
|
96
|
+
{#if !hideRowsPerPage}
|
|
97
|
+
<Dropdown
|
|
98
|
+
placeholder="Per pagina"
|
|
99
|
+
clearable={false}
|
|
100
|
+
mandatory={true}
|
|
101
|
+
bind:items={rowsPerPageOptions}
|
|
102
|
+
bind:values={rowsPerPageSelection}
|
|
103
|
+
--button-default-width="90px"
|
|
104
|
+
on:change={handleRowsPerPageChange}
|
|
105
|
+
></Dropdown>
|
|
106
|
+
{/if}
|
|
107
|
+
{#if totalElements !== undefined}
|
|
108
|
+
<slot name="rangeDescriptor" {page} {maxPage} {rowsPerPage} {totalElements}>
|
|
109
|
+
<div class="range-descriptor">
|
|
110
|
+
viewing {((page || 1) - 1) * rowsPerPage} - {(page || 1) * rowsPerPage} of {totalElements}
|
|
111
|
+
</div>
|
|
112
|
+
</slot>
|
|
113
|
+
{/if}
|
|
114
|
+
<Paginator
|
|
115
|
+
bind:page
|
|
116
|
+
bind:maxPage
|
|
117
|
+
on:change={handlePaginationChange}
|
|
118
|
+
></Paginator>
|
|
119
|
+
</slot>
|
|
123
120
|
</div>
|
|
124
121
|
</div>
|
|
125
122
|
|
|
126
123
|
<style>
|
|
127
|
-
.
|
|
124
|
+
.paginated-table {
|
|
125
|
+
width: 100%;
|
|
128
126
|
display: flex;
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
gap: 24px;
|
|
129
|
+
align-items: center;
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
color: var(--global-light-contrast-color);
|
|
140
|
-
font-size: .9rem;
|
|
132
|
+
.header-sort-icon {
|
|
133
|
+
display: none;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.header-sort-icon.active {
|
|
137
|
+
display: inline;
|
|
141
138
|
}
|
|
142
139
|
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
.range-descriptor {
|
|
141
|
+
font-size: .7rem;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.footer {
|
|
146
145
|
display: flex;
|
|
147
|
-
justify-content:
|
|
146
|
+
justify-content: space-between;
|
|
148
147
|
align-items: center;
|
|
149
|
-
|
|
150
|
-
font-size: .9rem;
|
|
148
|
+
width: 100%;
|
|
151
149
|
}
|
|
152
|
-
</style>
|
|
150
|
+
</style>
|
|
@@ -1,10 +1,76 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import SimpleTable from "../../simple/lists/SimpleTable.svelte";
|
|
3
|
+
import Paginator from "./Paginator.svelte";
|
|
4
|
+
import Dropdown from "../forms/Dropdown.svelte";
|
|
5
|
+
import { type ComponentProps } from "svelte";
|
|
6
|
+
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
|
7
|
+
export type Header = ArrayElement<NonNullable<ComponentProps<SimpleTable>['headers']>>;
|
|
2
8
|
declare const __propDef: {
|
|
3
|
-
props:
|
|
9
|
+
props: {
|
|
10
|
+
class?: {
|
|
11
|
+
simpleTable?: ComponentProps<SimpleTable>['class'];
|
|
12
|
+
} | undefined;
|
|
13
|
+
headers?: ComponentProps<SimpleTable>['headers'];
|
|
14
|
+
items?: ComponentProps<SimpleTable>['items'];
|
|
15
|
+
sortedBy?: ComponentProps<SimpleTable>['sortedBy'];
|
|
16
|
+
sortDirection?: ComponentProps<SimpleTable>['sortDirection'];
|
|
17
|
+
page?: number | undefined;
|
|
18
|
+
maxPage?: ComponentProps<Paginator>['maxPage'];
|
|
19
|
+
rowsPerPageOptions?: ComponentProps<Dropdown>['items'];
|
|
20
|
+
hideRowsPerPage?: boolean | undefined;
|
|
21
|
+
totalElements?: number | undefined;
|
|
22
|
+
rowsPerPage?: number | undefined;
|
|
23
|
+
};
|
|
4
24
|
events: {
|
|
25
|
+
sort: CustomEvent<{
|
|
26
|
+
sortedBy: string | undefined;
|
|
27
|
+
sortDirection: string;
|
|
28
|
+
}>;
|
|
29
|
+
} & {
|
|
5
30
|
[evt: string]: CustomEvent<any>;
|
|
6
31
|
};
|
|
7
|
-
slots: {
|
|
32
|
+
slots: {
|
|
33
|
+
header: {
|
|
34
|
+
head: import("../../simple/lists/SimpleTable.svelte").Header;
|
|
35
|
+
};
|
|
36
|
+
headerLabel: {};
|
|
37
|
+
custom: {
|
|
38
|
+
index: any;
|
|
39
|
+
columnIndex: any;
|
|
40
|
+
header: import("../../simple/lists/SimpleTable.svelte").Header;
|
|
41
|
+
item: {
|
|
42
|
+
[key: string]: any;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
rowActions: {
|
|
46
|
+
index: any;
|
|
47
|
+
item: {
|
|
48
|
+
[key: string]: any;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
append: {
|
|
52
|
+
index: any;
|
|
53
|
+
item: {
|
|
54
|
+
[key: string]: any;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
footer: {
|
|
58
|
+
hideRowsPerPage: boolean;
|
|
59
|
+
rowsPerPageOptions: import("../forms/Dropdown.svelte").Item[] | undefined;
|
|
60
|
+
rowsPerPageSelection: import("../forms/Dropdown.svelte").Item[];
|
|
61
|
+
totalElements: number | undefined;
|
|
62
|
+
page: number;
|
|
63
|
+
maxPage: number | undefined;
|
|
64
|
+
rowsPerPage: number;
|
|
65
|
+
handlePaginationChange: () => void;
|
|
66
|
+
};
|
|
67
|
+
rangeDescriptor: {
|
|
68
|
+
page: number;
|
|
69
|
+
maxPage: number | undefined;
|
|
70
|
+
rowsPerPage: number;
|
|
71
|
+
totalElements: number | undefined;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
8
74
|
};
|
|
9
75
|
export type PaginatedTableProps = typeof __propDef.props;
|
|
10
76
|
export type PaginatedTableEvents = typeof __propDef.events;
|
|
@@ -47,7 +47,8 @@ $:
|
|
|
47
47
|
icon="mdi-chevron-double-left"
|
|
48
48
|
on:click={hardPrevious}
|
|
49
49
|
--button-default-background-color="transparent"
|
|
50
|
-
--button-default-focus-background-color="
|
|
50
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
51
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
51
52
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
52
53
|
--button-default-box-shadow="none"
|
|
53
54
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
@@ -56,7 +57,8 @@ $:
|
|
|
56
57
|
icon="mdi-chevron-left"
|
|
57
58
|
on:click={previousPage}
|
|
58
59
|
--button-default-background-color="transparent"
|
|
59
|
-
--button-default-focus-background-color="
|
|
60
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
61
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
60
62
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
61
63
|
--button-default-box-shadow="none"
|
|
62
64
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
@@ -65,7 +67,8 @@ $:
|
|
|
65
67
|
<Button
|
|
66
68
|
on:click={() => goToPage(page - 1)}
|
|
67
69
|
--button-default-background-color="transparent"
|
|
68
|
-
--button-default-focus-background-color="
|
|
70
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
71
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
69
72
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
70
73
|
--button-default-box-shadow="none"
|
|
71
74
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
@@ -82,7 +85,8 @@ $:
|
|
|
82
85
|
<Button
|
|
83
86
|
on:click={() => goToPage(page + 1)}
|
|
84
87
|
--button-default-background-color="transparent"
|
|
85
|
-
--button-default-focus-background-color="
|
|
88
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
89
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
86
90
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
87
91
|
--button-default-box-shadow="none"
|
|
88
92
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
@@ -93,7 +97,8 @@ $:
|
|
|
93
97
|
on:click={nextPage}
|
|
94
98
|
icon="mdi-chevron-right"
|
|
95
99
|
--button-default-background-color="transparent"
|
|
96
|
-
--button-default-focus-background-color="
|
|
100
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
101
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
97
102
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
98
103
|
--button-default-box-shadow="none"
|
|
99
104
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
@@ -103,7 +108,8 @@ $:
|
|
|
103
108
|
on:click={hardNext}
|
|
104
109
|
icon="mdi-chevron-double-right"
|
|
105
110
|
--button-default-background-color="transparent"
|
|
106
|
-
--button-default-focus-background-color="
|
|
111
|
+
--button-default-focus-background-color="rgb(var(--global-color-primary-500), .3)"
|
|
112
|
+
--button-default-focus-color="rgb(var(--global-color-contrast-900))"
|
|
107
113
|
--button-default-hover-background-color="rgb(var(--global-color-primary-500))"
|
|
108
114
|
--button-default-box-shadow="none"
|
|
109
115
|
--button-default-color="rgb(var(--global-color-contrast-900))"
|
|
File without changes
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script context="module"></script>
|
|
2
|
+
|
|
3
|
+
<script>import "./Filters.css";
|
|
4
|
+
import "../../../css/main.css";
|
|
5
|
+
import Drawer from "../../simple/navigation/Drawer.svelte";
|
|
6
|
+
import Menu from "../../simple/common/Menu.svelte";
|
|
7
|
+
import MediaQuery from "../../simple/common/MediaQuery.svelte";
|
|
8
|
+
import Button from "../../simple/buttons/Button.svelte";
|
|
9
|
+
import Icon from "../../simple/media/Icon.svelte";
|
|
10
|
+
import { createEventDispatcher } from "svelte";
|
|
11
|
+
import SelectableVerticalList from "../../simple/lists/SelectableVerticalList.svelte";
|
|
12
|
+
export let addFilterLabel = "Add filter", filters = [];
|
|
13
|
+
let dispatch = createEventDispatcher();
|
|
14
|
+
let open = false, activator;
|
|
15
|
+
function handleAddFilterClick() {
|
|
16
|
+
dispatch("addFilterClick");
|
|
17
|
+
open = true;
|
|
18
|
+
}
|
|
19
|
+
$:
|
|
20
|
+
filterOptions = filters.map((f) => {
|
|
21
|
+
return {
|
|
22
|
+
title: f.label,
|
|
23
|
+
name: f.name
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
let selected;
|
|
27
|
+
let focused;
|
|
28
|
+
$:
|
|
29
|
+
if (!!selected)
|
|
30
|
+
selected = void 0;
|
|
31
|
+
$:
|
|
32
|
+
if (!!focused && !open)
|
|
33
|
+
focused = void 0;
|
|
34
|
+
function handleFilterSelection() {
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div
|
|
40
|
+
class="add-filter-button"
|
|
41
|
+
bind:this={activator}
|
|
42
|
+
>
|
|
43
|
+
<Button
|
|
44
|
+
on:click={handleAddFilterClick}
|
|
45
|
+
>
|
|
46
|
+
<Icon name="mdi-plus"></Icon>
|
|
47
|
+
{addFilterLabel}
|
|
48
|
+
</Button>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<MediaQuery let:mAndDown>
|
|
52
|
+
{#if mAndDown}
|
|
53
|
+
<Drawer
|
|
54
|
+
bind:open={open}
|
|
55
|
+
position="bottom"
|
|
56
|
+
on:item-click
|
|
57
|
+
>
|
|
58
|
+
<SelectableVerticalList
|
|
59
|
+
bind:selected
|
|
60
|
+
bind:focused
|
|
61
|
+
bind:elements={filterOptions}
|
|
62
|
+
--selectable-vertical-list-default-width="100%"
|
|
63
|
+
--selectable-vertical-list-default-element-height="56px"
|
|
64
|
+
--selectable-vertical-list-default-title-font-size="null"
|
|
65
|
+
on:select={handleFilterSelection}
|
|
66
|
+
></SelectableVerticalList>
|
|
67
|
+
</Drawer>
|
|
68
|
+
{:else}
|
|
69
|
+
<Menu
|
|
70
|
+
bind:activator={activator}
|
|
71
|
+
bind:open={open}
|
|
72
|
+
closeOnClickOutside
|
|
73
|
+
_boxShadow="rgb(var(--global-color-grey-900), .5) 0px 2px 4px"
|
|
74
|
+
_height="fit-content"
|
|
75
|
+
_maxHeight="300px"
|
|
76
|
+
_minWidth="100px"
|
|
77
|
+
_borderRadius="5px"
|
|
78
|
+
anchor="bottom-center"
|
|
79
|
+
>
|
|
80
|
+
<SelectableVerticalList
|
|
81
|
+
bind:selected
|
|
82
|
+
bind:focused
|
|
83
|
+
bind:elements={filterOptions}
|
|
84
|
+
--selectable-vertical-list-default-width="100%"
|
|
85
|
+
--selectable-vertical-list-default-element-height="56px"
|
|
86
|
+
--selectable-vertical-list-default-title-font-size="null"
|
|
87
|
+
on:select={handleFilterSelection}
|
|
88
|
+
></SelectableVerticalList>
|
|
89
|
+
</Menu>
|
|
90
|
+
{/if}
|
|
91
|
+
</MediaQuery>
|
|
92
|
+
|
|
93
|
+
<style>
|
|
94
|
+
.add-filter-button {
|
|
95
|
+
width: fit-content;
|
|
96
|
+
}
|
|
97
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
export type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
|
3
|
+
import './Filters.css';
|
|
4
|
+
import '../../../css/main.css';
|
|
5
|
+
import type { Filter } from '../../../utils/filters/filters';
|
|
6
|
+
declare const __propDef: {
|
|
7
|
+
props: {
|
|
8
|
+
addFilterLabel?: string | undefined;
|
|
9
|
+
filters?: Filter[] | undefined;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
'item-click': CustomEvent<{
|
|
13
|
+
item: import("../../simple/navigation/Navigator.svelte").Item;
|
|
14
|
+
}>;
|
|
15
|
+
addFilterClick: CustomEvent<undefined>;
|
|
16
|
+
} & {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
};
|
|
19
|
+
slots: {};
|
|
20
|
+
};
|
|
21
|
+
export type FiltersProps = typeof __propDef.props;
|
|
22
|
+
export type FiltersEvents = typeof __propDef.events;
|
|
23
|
+
export type FiltersSlots = typeof __propDef.slots;
|
|
24
|
+
export default class Filters extends SvelteComponentTyped<FiltersProps, FiltersEvents, FiltersSlots> {
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--button-default-text-hover-background-color: rgb(var(--global-color-primary-500), 0.2);
|
|
15
15
|
--button-default-active-background-color: rgb(var(--global-color-primary-500));
|
|
16
16
|
--button-default-focus-background-color: rgb(var(--global-color-primary-500));
|
|
17
|
+
--button-default-focus-color: rgb(var(--global-color-grey-50));
|
|
17
18
|
--button-default-disabled-background-color: rgb(var(--global-color-primary-500), .6);
|
|
18
19
|
--button-default-disabled-color: rgb(var(--global-color-grey-50), .6);
|
|
19
20
|
--button-default-text-active-background-color: rgb(var(--global-color-primary-500), 0.4);
|
|
@@ -199,6 +199,10 @@ import CircularLoader from "../loaders/CircularLoader.svelte";
|
|
|
199
199
|
--button-focus-background-color,
|
|
200
200
|
var(--button-default-focus-background-color)
|
|
201
201
|
);
|
|
202
|
+
color: var(
|
|
203
|
+
--button-focus-color,
|
|
204
|
+
var(--button-default-focus-color)
|
|
205
|
+
);
|
|
202
206
|
}
|
|
203
207
|
|
|
204
208
|
.button-text {
|
|
@@ -5,7 +5,7 @@ import "./Autocomplete.css";
|
|
|
5
5
|
import { scrollInMenu } from "../common/scroller";
|
|
6
6
|
let clazz = {};
|
|
7
7
|
export { clazz as class };
|
|
8
|
-
export let values = [], items, searchFunction = void 0, multiple = false, disabled = false, placeholder = "", width = "auto", height = "auto", maxWidth = void 0, openingId = "autocomplete-menu", searchText = void 0, maxVisibleChips = void 0, menuBoxShadow = "rgb(var(--global-color-background-300), .5) 0px 2px 4px", menuBorderRadius = "5px";
|
|
8
|
+
export let values = [], items, searchFunction = void 0, multiple = false, disabled = false, mandatory = false, placeholder = "", width = "auto", height = "auto", maxWidth = void 0, openingId = "autocomplete-menu", searchText = void 0, maxVisibleChips = void 0, menuBoxShadow = "rgb(var(--global-color-background-300), .5) 0px 2px 4px", menuBorderRadius = "5px";
|
|
9
9
|
let dispatch = createEventDispatcher();
|
|
10
10
|
function select(item) {
|
|
11
11
|
const alreadyPresent = values.findIndex((i) => i.value === item.value) != -1;
|
|
@@ -23,6 +23,8 @@ function select(item) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
function unselect(item) {
|
|
26
|
+
if (values.length == 1 && mandatory)
|
|
27
|
+
return;
|
|
26
28
|
values = values.filter((i) => i.value != item.value);
|
|
27
29
|
refreshMenuWidth();
|
|
28
30
|
dispatch("change", {
|
|
@@ -32,6 +34,8 @@ function unselect(item) {
|
|
|
32
34
|
});
|
|
33
35
|
}
|
|
34
36
|
function pop() {
|
|
37
|
+
if (values.length == 1 && mandatory)
|
|
38
|
+
return;
|
|
35
39
|
let poppedElement = values.pop();
|
|
36
40
|
values = [...values];
|
|
37
41
|
refreshMenuWidth();
|
|
@@ -17,6 +17,7 @@ declare const __propDef: {
|
|
|
17
17
|
searchFunction?: ((item: Item, searchText: string | undefined) => boolean) | undefined;
|
|
18
18
|
multiple?: boolean | undefined;
|
|
19
19
|
disabled?: boolean | undefined;
|
|
20
|
+
mandatory?: boolean | undefined;
|
|
20
21
|
placeholder?: string | undefined;
|
|
21
22
|
width?: string | undefined;
|
|
22
23
|
height?: string | undefined;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
<script>import "../../../css/main.css";
|
|
4
4
|
import "./SimpleTable.css";
|
|
5
|
-
import { dateToString } from "../dates/utils";
|
|
6
5
|
import Icon from "../media/Icon.svelte";
|
|
7
6
|
import { createEventDispatcher } from "svelte";
|
|
8
7
|
let clazz = {};
|
|
@@ -25,6 +24,9 @@ function handleHeaderClick(header) {
|
|
|
25
24
|
sortDirection
|
|
26
25
|
});
|
|
27
26
|
}
|
|
27
|
+
function formatDate(dateTime, dateFormat) {
|
|
28
|
+
return dateTime.setLocale(dateFormat.locale).toFormat(dateFormat.format);
|
|
29
|
+
}
|
|
28
30
|
</script>
|
|
29
31
|
|
|
30
32
|
{#if !!items && Array.isArray(items)}
|
|
@@ -33,8 +35,8 @@ function handleHeaderClick(header) {
|
|
|
33
35
|
<thead class="thead {clazz.header || ''}">
|
|
34
36
|
<tr>
|
|
35
37
|
{#each headers as head}
|
|
36
|
-
<th
|
|
37
|
-
style:width={head.width}
|
|
38
|
+
<th
|
|
39
|
+
style:width={head.width}
|
|
38
40
|
style:min-width={head.minWidth}
|
|
39
41
|
class:sortable={head.sortable}
|
|
40
42
|
on:click={() => handleHeaderClick(head)}
|
|
@@ -46,16 +48,16 @@ function handleHeaderClick(header) {
|
|
|
46
48
|
</slot>
|
|
47
49
|
</span>
|
|
48
50
|
{#if head.sortable}
|
|
49
|
-
<span
|
|
51
|
+
<span
|
|
50
52
|
class="header-sort-icon"
|
|
51
53
|
class:active={sortedBy == head.value}
|
|
52
|
-
class:asc={sortDirection ==
|
|
53
|
-
class:desc={sortDirection ==
|
|
54
|
+
class:asc={sortDirection == "asc"}
|
|
55
|
+
class:desc={sortDirection == "desc"}
|
|
54
56
|
>
|
|
55
|
-
{#if sortDirection ==
|
|
56
|
-
<Icon name="mdi-arrow-up"
|
|
57
|
+
{#if sortDirection == "asc"}
|
|
58
|
+
<Icon name="mdi-arrow-up" />
|
|
57
59
|
{:else}
|
|
58
|
-
<Icon name="mdi-arrow-down"
|
|
60
|
+
<Icon name="mdi-arrow-down" />
|
|
59
61
|
{/if}
|
|
60
62
|
</span>
|
|
61
63
|
{/if}
|
|
@@ -74,7 +76,7 @@ function handleHeaderClick(header) {
|
|
|
74
76
|
<tr class="item-tr {clazz.row || ''}">
|
|
75
77
|
{#each headers as header, j}
|
|
76
78
|
<td class="{clazz.cell || ''}">
|
|
77
|
-
{#if header.type == "custom"}
|
|
79
|
+
{#if header.type.key == "custom"}
|
|
78
80
|
<slot
|
|
79
81
|
name="custom"
|
|
80
82
|
index={i}
|
|
@@ -82,9 +84,15 @@ function handleHeaderClick(header) {
|
|
|
82
84
|
{header}
|
|
83
85
|
{item}
|
|
84
86
|
/>
|
|
85
|
-
{:else if
|
|
86
|
-
{
|
|
87
|
-
{:else}
|
|
87
|
+
{:else if header.type.key == "date"}
|
|
88
|
+
{formatDate(item[header.value], header.type.params)}
|
|
89
|
+
{:else if header.type.key == "icon"}
|
|
90
|
+
<Icon
|
|
91
|
+
--icon-color={header.type.params?.color }
|
|
92
|
+
--icon-size={header.type.params?.size}
|
|
93
|
+
name={header.type.params?.name || ''}
|
|
94
|
+
/>
|
|
95
|
+
{:else}
|
|
88
96
|
{item[header.value]}
|
|
89
97
|
{/if}
|
|
90
98
|
</td>
|
|
@@ -104,10 +112,7 @@ function handleHeaderClick(header) {
|
|
|
104
112
|
|
|
105
113
|
<style>
|
|
106
114
|
.simple-table-container {
|
|
107
|
-
width: var(
|
|
108
|
-
--simple-table-width,
|
|
109
|
-
var(--simple-table-default-width)
|
|
110
|
-
);
|
|
115
|
+
width: var(--simple-table-width, var(--simple-table-default-width));
|
|
111
116
|
min-width: var(
|
|
112
117
|
--simple-table-min-width,
|
|
113
118
|
var(--simple-table-default-min-width)
|
|
@@ -116,10 +121,7 @@ function handleHeaderClick(header) {
|
|
|
116
121
|
--simple-table-max-width,
|
|
117
122
|
var(--simple-table-default-max-width)
|
|
118
123
|
);
|
|
119
|
-
height: var(
|
|
120
|
-
--simple-table-height,
|
|
121
|
-
var(--simple-table-default-height)
|
|
122
|
-
);
|
|
124
|
+
height: var(--simple-table-height, var(--simple-table-default-height));
|
|
123
125
|
min-height: var(
|
|
124
126
|
--simple-table-min-height,
|
|
125
127
|
var(--simple-table-default-min-height)
|
|
@@ -158,7 +160,7 @@ function handleHeaderClick(header) {
|
|
|
158
160
|
|
|
159
161
|
.thead th.sortable {
|
|
160
162
|
cursor: pointer;
|
|
161
|
-
transition: all .1s ease-in;
|
|
163
|
+
transition: all 0.1s ease-in;
|
|
162
164
|
user-select: none;
|
|
163
165
|
}
|
|
164
166
|
|
|
@@ -221,7 +223,7 @@ function handleHeaderClick(header) {
|
|
|
221
223
|
--simple-table-row-height,
|
|
222
224
|
var(--simple-table-default-row-height)
|
|
223
225
|
);
|
|
224
|
-
transition: background-color .1s ease-in-out;
|
|
226
|
+
transition: background-color 0.1s ease-in-out;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
.item-tr:hover {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
export type HeaderType = ColumnBoolean | ColumnString | ColumnNumber | ColumnDate | ColumnIcon | ColumnCheckBox | ColumnCostom;
|
|
2
3
|
export type Header = {
|
|
3
4
|
value: string;
|
|
4
5
|
label: string;
|
|
5
|
-
type:
|
|
6
|
+
type: HeaderType;
|
|
6
7
|
width?: string;
|
|
7
8
|
minWidth?: string;
|
|
8
9
|
sortable?: boolean;
|
|
@@ -12,6 +13,7 @@ export type Header = {
|
|
|
12
13
|
};
|
|
13
14
|
import '../../../css/main.css';
|
|
14
15
|
import './SimpleTable.css';
|
|
16
|
+
import type { ColumnBoolean, ColumnCheckBox, ColumnCostom, ColumnDate, ColumnIcon, ColumnNumber, ColumnString } from './columnTypes';
|
|
15
17
|
declare const __propDef: {
|
|
16
18
|
props: {
|
|
17
19
|
class?: {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type ColumnDate = {
|
|
2
|
+
key: "date";
|
|
3
|
+
params: {
|
|
4
|
+
format: string;
|
|
5
|
+
locale: string;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export type ColumnIcon = {
|
|
9
|
+
key: "icon";
|
|
10
|
+
params: {
|
|
11
|
+
name: string;
|
|
12
|
+
color: string;
|
|
13
|
+
size: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export type ColumnBoolean = {
|
|
17
|
+
key: "boolean";
|
|
18
|
+
params?: {};
|
|
19
|
+
};
|
|
20
|
+
export type ColumnString = {
|
|
21
|
+
key: "string";
|
|
22
|
+
params?: {};
|
|
23
|
+
};
|
|
24
|
+
export type ColumnNumber = {
|
|
25
|
+
key: "number";
|
|
26
|
+
params?: {};
|
|
27
|
+
};
|
|
28
|
+
export type ColumnCostom = {
|
|
29
|
+
key: "custom";
|
|
30
|
+
params?: {};
|
|
31
|
+
};
|
|
32
|
+
export type ColumnCheckBox = {
|
|
33
|
+
key: "checkbox";
|
|
34
|
+
params?: {};
|
|
35
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export { default as ProgressBar } from './components/simple/progress/ProgressBar
|
|
|
46
46
|
export { default as ProductCard } from './components/composed/shop/ProductCard.svelte';
|
|
47
47
|
export { default as ProductsGrid } from './components/composed/shop/ProductsGrid.svelte';
|
|
48
48
|
export { default as PaginatedTable } from './components/composed/list/PaginatedTable.svelte';
|
|
49
|
+
export { default as Filters } from './components/composed/search/Filters.svelte';
|
|
49
50
|
export { default as mediaQuery } from './stores/mediaQuery';
|
|
50
51
|
export { default as theme, toggleTheme, setTheme } from './stores/theme';
|
|
51
52
|
export { default as SimpleTimeLine } from './components/simple/timeline/SimpleTimeLine.svelte';
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ export { default as ProgressBar } from './components/simple/progress/ProgressBar
|
|
|
46
46
|
export { default as ProductCard } from './components/composed/shop/ProductCard.svelte';
|
|
47
47
|
export { default as ProductsGrid } from './components/composed/shop/ProductsGrid.svelte';
|
|
48
48
|
export { default as PaginatedTable } from './components/composed/list/PaginatedTable.svelte';
|
|
49
|
+
export { default as Filters } from './components/composed/search/Filters.svelte';
|
|
49
50
|
export { default as mediaQuery } from './stores/mediaQuery';
|
|
50
51
|
export { default as theme, toggleTheme, setTheme } from './stores/theme';
|
|
51
52
|
export { default as SimpleTimeLine } from './components/simple/timeline/SimpleTimeLine.svelte';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { JoinModifier } from "./modifiers/join";
|
|
2
|
+
import type { WhereModifier } from "./modifiers/where";
|
|
3
|
+
export type Modifier = WhereModifier | JoinModifier;
|
|
4
|
+
export type JsonQuery = {
|
|
5
|
+
modifiers: Modifier[];
|
|
6
|
+
};
|
|
7
|
+
export default class Builder {
|
|
8
|
+
private modifiers;
|
|
9
|
+
constructor();
|
|
10
|
+
where(callback: (builder: Builder) => void): Builder;
|
|
11
|
+
where(key: Record<string, string | number | Date>): Builder;
|
|
12
|
+
where(key: string, value: string | number | Date): Builder;
|
|
13
|
+
where(key: string, operator: string, value: string | number | Date): Builder;
|
|
14
|
+
whereNot(callback: (builder: Builder) => void): Builder;
|
|
15
|
+
whereNot(key: Record<string, string | number | Date>): Builder;
|
|
16
|
+
whereNot(key: string, value: string | number | Date): Builder;
|
|
17
|
+
whereNot(key: string, operator: string, value: string | number | Date): Builder;
|
|
18
|
+
orWhere(callback: (builder: Builder) => void): Builder;
|
|
19
|
+
orWhere(key: Record<string, string | number | Date>): Builder;
|
|
20
|
+
orWhere(key: string, value: string | number | Date): Builder;
|
|
21
|
+
orWhere(key: string, operator: string, value: string | number | Date): Builder;
|
|
22
|
+
orWhereNot(callback: (builder: Builder) => void): Builder;
|
|
23
|
+
orWhereNot(key: Record<string, string | number | Date>): Builder;
|
|
24
|
+
orWhereNot(key: string, value: string | number | Date): Builder;
|
|
25
|
+
orWhereNot(key: string, operator: string, value: string | number | Date): Builder;
|
|
26
|
+
private applyWhereClause;
|
|
27
|
+
join(table: string, onCallback: (onBuilder: OnClauseBuilder) => void): this;
|
|
28
|
+
leftJoin(table: string, onCallback: (onBuilder: OnClauseBuilder) => void): this;
|
|
29
|
+
rightJoin(table: string, onCallback: (onBuilder: OnClauseBuilder) => void): this;
|
|
30
|
+
private applyJoinClause;
|
|
31
|
+
toJson(): JsonQuery;
|
|
32
|
+
}
|
|
33
|
+
import type { JoinModifierOnClause } from "./modifiers/join";
|
|
34
|
+
declare class OnClauseBuilder {
|
|
35
|
+
private onClauses;
|
|
36
|
+
constructor();
|
|
37
|
+
get json(): JoinModifierOnClause[];
|
|
38
|
+
on(from: string, to: string): void;
|
|
39
|
+
on(from: string, operator: string, to: string): void;
|
|
40
|
+
orOn(from: string, to: string): void;
|
|
41
|
+
orOn(from: string, operator: string, to: string): void;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export default class Builder {
|
|
2
|
+
modifiers = [];
|
|
3
|
+
constructor() {
|
|
4
|
+
this.modifiers = [];
|
|
5
|
+
}
|
|
6
|
+
where(first, second, third) {
|
|
7
|
+
return this.applyWhereClause('and', first, second, third);
|
|
8
|
+
}
|
|
9
|
+
whereNot(first, second, third) {
|
|
10
|
+
return this.applyWhereClause('and', first, second, third);
|
|
11
|
+
}
|
|
12
|
+
orWhere(first, second, third) {
|
|
13
|
+
return this.applyWhereClause('or', first, second, third);
|
|
14
|
+
}
|
|
15
|
+
orWhereNot(first, second, third) {
|
|
16
|
+
return this.applyWhereClause('orNot', first, second, third);
|
|
17
|
+
}
|
|
18
|
+
applyWhereClause(logicalOperator, first, second, third) {
|
|
19
|
+
if (!!third) {
|
|
20
|
+
if (!!second && typeof first == 'string' && typeof second == 'string') {
|
|
21
|
+
this.modifiers.push({
|
|
22
|
+
method: 'where',
|
|
23
|
+
kind: 'simple',
|
|
24
|
+
key: first,
|
|
25
|
+
operator: second,
|
|
26
|
+
value: third,
|
|
27
|
+
logicalOperator: logicalOperator
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else if (typeof first == 'object') {
|
|
31
|
+
this.modifiers.push({
|
|
32
|
+
method: 'where',
|
|
33
|
+
kind: 'object',
|
|
34
|
+
values: first,
|
|
35
|
+
logicalOperator
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (typeof first == 'string' && !!second) {
|
|
40
|
+
this.modifiers.push({
|
|
41
|
+
method: 'where',
|
|
42
|
+
kind: 'simple',
|
|
43
|
+
key: first,
|
|
44
|
+
value: second,
|
|
45
|
+
logicalOperator
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else if (typeof first == 'function') {
|
|
49
|
+
let builder = new Builder();
|
|
50
|
+
first(builder);
|
|
51
|
+
if (!builder.modifiers.every(el => el.method == 'where'))
|
|
52
|
+
throw new Error('inconsistent json query from where callback');
|
|
53
|
+
this.modifiers.push({
|
|
54
|
+
method: 'where',
|
|
55
|
+
kind: 'grouped',
|
|
56
|
+
logicalOperator,
|
|
57
|
+
children: builder.modifiers.filter((el) => el.method == 'where')
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
join(table, onCallback) {
|
|
63
|
+
let onBuilder = new OnClauseBuilder();
|
|
64
|
+
onCallback(onBuilder);
|
|
65
|
+
this.applyJoinClause('inner', table, onBuilder.json);
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
leftJoin(table, onCallback) {
|
|
69
|
+
let onBuilder = new OnClauseBuilder();
|
|
70
|
+
onCallback(onBuilder);
|
|
71
|
+
this.applyJoinClause('left', table, onBuilder.json);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
rightJoin(table, onCallback) {
|
|
75
|
+
let onBuilder = new OnClauseBuilder();
|
|
76
|
+
onCallback(onBuilder);
|
|
77
|
+
this.applyJoinClause('right', table, onBuilder.json);
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
applyJoinClause(kind, table, on) {
|
|
81
|
+
this.modifiers.push({
|
|
82
|
+
method: 'join',
|
|
83
|
+
kind: kind,
|
|
84
|
+
on: on,
|
|
85
|
+
table: table
|
|
86
|
+
});
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
toJson() {
|
|
90
|
+
return {
|
|
91
|
+
modifiers: this.modifiers
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
class OnClauseBuilder {
|
|
96
|
+
onClauses;
|
|
97
|
+
constructor() {
|
|
98
|
+
this.onClauses = [];
|
|
99
|
+
}
|
|
100
|
+
get json() {
|
|
101
|
+
return this.onClauses;
|
|
102
|
+
}
|
|
103
|
+
on(first, second, third) {
|
|
104
|
+
if (!third) {
|
|
105
|
+
this.onClauses.push({
|
|
106
|
+
from: first,
|
|
107
|
+
operator: '=',
|
|
108
|
+
to: second
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.onClauses.push({
|
|
113
|
+
from: first,
|
|
114
|
+
operator: second,
|
|
115
|
+
to: third
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
orOn(first, second, third) {
|
|
120
|
+
if (!third) {
|
|
121
|
+
this.onClauses.push({
|
|
122
|
+
from: first,
|
|
123
|
+
operator: '=',
|
|
124
|
+
to: second,
|
|
125
|
+
logicalOperator: 'or'
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.onClauses.push({
|
|
130
|
+
from: first,
|
|
131
|
+
operator: second,
|
|
132
|
+
to: third,
|
|
133
|
+
logicalOperator: 'or'
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import Builder from "./builder";
|
|
2
|
+
type MultiStringFilter = {
|
|
3
|
+
type: 'multiString';
|
|
4
|
+
columns: string[];
|
|
5
|
+
operator?: 'or' | 'and';
|
|
6
|
+
};
|
|
7
|
+
type StringFilter = {
|
|
8
|
+
type: 'string';
|
|
9
|
+
column: string;
|
|
10
|
+
value: string | undefined;
|
|
11
|
+
mode?: 'equal' | 'like' | 'ilike';
|
|
12
|
+
};
|
|
13
|
+
export type Filter = {
|
|
14
|
+
name: string;
|
|
15
|
+
active: boolean;
|
|
16
|
+
hidden?: boolean;
|
|
17
|
+
label: string;
|
|
18
|
+
} & (StringFilter | MultiStringFilter);
|
|
19
|
+
export default class Converter {
|
|
20
|
+
constructor();
|
|
21
|
+
createBuilder(params: {
|
|
22
|
+
filters: Filter[];
|
|
23
|
+
}): Builder;
|
|
24
|
+
private applyStringFilter;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Builder from "./builder";
|
|
2
|
+
export default class Converter {
|
|
3
|
+
constructor() {
|
|
4
|
+
}
|
|
5
|
+
createBuilder(params) {
|
|
6
|
+
let builder = new Builder();
|
|
7
|
+
for (let i = 0; i < params.filters.length; i += 1) {
|
|
8
|
+
const filter = params.filters[i];
|
|
9
|
+
if (filter.type == 'string') {
|
|
10
|
+
this.applyStringFilter({ builder, filter });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return builder;
|
|
14
|
+
}
|
|
15
|
+
applyStringFilter(params) {
|
|
16
|
+
if (params.filter.value === undefined)
|
|
17
|
+
return params.builder;
|
|
18
|
+
if (params.filter.mode == 'like') {
|
|
19
|
+
params.builder.where(params.filter.column, 'like', params.filter.value);
|
|
20
|
+
}
|
|
21
|
+
else if (params.filter.mode == 'ilike') {
|
|
22
|
+
params.builder.where(params.filter.column, 'ilike', params.filter.value);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
params.builder.where(params.filter.column, '=', params.filter.value);
|
|
26
|
+
}
|
|
27
|
+
return params.builder;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type JoinModifierOnClause = {
|
|
2
|
+
from: string;
|
|
3
|
+
operator: string;
|
|
4
|
+
to: string;
|
|
5
|
+
logicalOperator?: 'and' | 'or';
|
|
6
|
+
};
|
|
7
|
+
type RightJoinModifier = {
|
|
8
|
+
method: 'join';
|
|
9
|
+
kind: 'right';
|
|
10
|
+
table: string;
|
|
11
|
+
on: JoinModifierOnClause[];
|
|
12
|
+
};
|
|
13
|
+
type InnerJoinModifier = {
|
|
14
|
+
method: 'join';
|
|
15
|
+
kind: 'inner';
|
|
16
|
+
table: string;
|
|
17
|
+
on: JoinModifierOnClause[];
|
|
18
|
+
};
|
|
19
|
+
type LeftJoinJsonModifier = {
|
|
20
|
+
method: 'join';
|
|
21
|
+
kind: 'left';
|
|
22
|
+
table: string;
|
|
23
|
+
on: JoinModifierOnClause[];
|
|
24
|
+
};
|
|
25
|
+
export type JoinModifier = LeftJoinJsonModifier | InnerJoinModifier | RightJoinModifier;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type GroupedWhere = {
|
|
2
|
+
method: 'where';
|
|
3
|
+
kind: 'grouped';
|
|
4
|
+
logicalOperator?: 'and' | 'or' | 'andNot' | 'orNot';
|
|
5
|
+
children: (ObjectWhere | SimpleWhere | GroupedWhere | InWhere)[];
|
|
6
|
+
};
|
|
7
|
+
type ObjectWhere = {
|
|
8
|
+
method: 'where';
|
|
9
|
+
kind: 'object';
|
|
10
|
+
logicalOperator?: 'and' | 'or' | 'andNot' | 'orNot';
|
|
11
|
+
values: Record<string, string | number | Date>;
|
|
12
|
+
};
|
|
13
|
+
type SimpleWhere = {
|
|
14
|
+
method: 'where';
|
|
15
|
+
kind: 'simple';
|
|
16
|
+
logicalOperator?: 'and' | 'or' | 'andNot' | 'orNot';
|
|
17
|
+
key: string;
|
|
18
|
+
operator?: string;
|
|
19
|
+
value: string | number | Date;
|
|
20
|
+
};
|
|
21
|
+
type InWhere = {
|
|
22
|
+
method: 'where';
|
|
23
|
+
kind: 'in';
|
|
24
|
+
logicalOperator?: 'and' | 'or' | 'andNot' | 'orNot';
|
|
25
|
+
key: string;
|
|
26
|
+
value: (string | number | Date)[];
|
|
27
|
+
};
|
|
28
|
+
export type WhereModifier = SimpleWhere | ObjectWhere | GroupedWhere | InWhere;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|