Skip to content

Commit 4c6d7f3

Browse files
committed
Restructure for proper library
Keep only library-relevant code in src/ directory. Move serve-related files for development to dev/ Change build script for targeting library mode.
1 parent 0a81f17 commit 4c6d7f3

11 files changed

+348
-54
lines changed

dev/App.vue

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<template>
2+
<div id="app">
3+
<query-builder
4+
:config="config"
5+
v-model="query"
6+
>
7+
<template #groupOperator="props">
8+
<div class="query-builder-group-slot__group-selection">
9+
<span class="query-builder-group-slot__group-operator">SLOT #groupOperator</span>
10+
<select
11+
:value="props.currentOperator"
12+
@input="props.updateCurrentOperator($event.target.value)"
13+
>
14+
<option disabled value="">Select an operator</option>
15+
<option
16+
v-for="operator in props.operators"
17+
:key="operator.identifier"
18+
:value="operator.identifier"
19+
v-text="operator.name"
20+
/>
21+
</select>
22+
</div>
23+
</template>
24+
25+
<template #groupControl="props">
26+
<group-ctrl-slot :group-ctrl="props"/>
27+
</template>
28+
29+
<template #rule="props">
30+
<rule-slot :ruleCtrl="props"/>
31+
</template>
32+
</query-builder>
33+
</div>
34+
</template>
35+
36+
<script lang="ts">
37+
import { Component, Vue } from 'vue-property-decorator';
38+
39+
import QueryBuilder from '@/QueryBuilder.vue';
40+
import { RuleSet, QueryBuilderConfig } from '@/types';
41+
42+
import InputSelection from './Input.vue';
43+
import NumberSelection from './Number.vue';
44+
import GroupCtrlSlot from './GroupCtrlSlot.vue';
45+
import RuleSlot from './RuleSlot.vue';
46+
47+
@Component({
48+
components: {
49+
QueryBuilder,
50+
GroupCtrlSlot,
51+
RuleSlot,
52+
},
53+
})
54+
export default class App extends Vue {
55+
query: RuleSet | null = {
56+
operatorIdentifier: 'OR',
57+
children: [
58+
{
59+
operatorIdentifier: 'AND',
60+
children: [
61+
{
62+
identifier: 'txt',
63+
value: 'A',
64+
},
65+
{
66+
identifier: 'txt',
67+
value: 'B',
68+
},
69+
{
70+
identifier: 'txt',
71+
value: 'C',
72+
},
73+
{
74+
operatorIdentifier: 'AND',
75+
children: [
76+
{
77+
identifier: 'txt',
78+
value: 'c',
79+
},
80+
{
81+
identifier: 'txt',
82+
value: 'd',
83+
},
84+
{
85+
operatorIdentifier: 'AND',
86+
children: [
87+
{
88+
identifier: 'txt',
89+
value: 'a',
90+
},
91+
{
92+
identifier: 'txt',
93+
value: 'b',
94+
},
95+
],
96+
},
97+
],
98+
},
99+
],
100+
},
101+
{
102+
operatorIdentifier: 'AND',
103+
children: [
104+
{
105+
identifier: 'txt',
106+
value: 'X',
107+
},
108+
{
109+
identifier: 'txt',
110+
value: 'Y',
111+
},
112+
{
113+
identifier: 'txt',
114+
value: 'Z',
115+
},
116+
],
117+
},
118+
],
119+
};
120+
121+
config: QueryBuilderConfig = {
122+
operators: [
123+
{
124+
name: 'AND',
125+
identifier: 'AND',
126+
},
127+
{
128+
name: 'OR',
129+
identifier: 'OR',
130+
},
131+
],
132+
rules: [
133+
{
134+
identifier: 'txt',
135+
name: 'Text Selection',
136+
component: InputSelection,
137+
initialValue: '',
138+
},
139+
{
140+
identifier: 'num',
141+
name: 'Number Selection',
142+
component: NumberSelection,
143+
initialValue: 10,
144+
},
145+
],
146+
colors: [
147+
'hsl(88, 50%, 55%)',
148+
'hsl(187, 100%, 45%)',
149+
'hsl(15, 100%, 55%)',
150+
],
151+
dragging: {
152+
animation: 300,
153+
disabled: false,
154+
ghostClass: 'ghost',
155+
},
156+
}
157+
}
158+
</script>
159+
160+
<style lang="scss">
161+
body {
162+
margin: 0;
163+
padding: 0;
164+
}
165+
166+
#app {
167+
margin: 30px auto;
168+
width: 90%;
169+
border: 1px solid hsl(0, 0%, 75%);
170+
}
171+
172+
.query-builder-group-slot__group-selection {
173+
padding: 16px;
174+
background-color: hsl(0, 0, 95%);
175+
}
176+
.query-builder-group-slot__group-operator {
177+
margin-right: 8px;
178+
}
179+
</style>

dev/GroupCtrlSlot.vue

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script lang="ts">
2+
import { Vue, Component, Prop } from 'vue-property-decorator';
3+
import { GroupCtrlSlotProps } from '@/types';
4+
5+
@Component
6+
export default class GroupCtrlSlot extends Vue {
7+
@Prop({ required: true }) readonly groupCtrl!: GroupCtrlSlotProps
8+
9+
selectedRule: string = ''
10+
}
11+
</script>
12+
13+
<template>
14+
<div class="query-builder-group-slot__group-control">
15+
SLOT #groupControl
16+
<select
17+
v-model="selectedRule"
18+
class="query-builder-group-slot__rule-selection"
19+
>
20+
<option disabled value="">Select a rule</option>
21+
<option
22+
v-for="rule in groupCtrl.rules"
23+
:key="rule.identifier"
24+
:value="rule.identifier"
25+
v-text="rule.name"
26+
/>
27+
</select>
28+
<button
29+
:disabled="selectedRule === ''"
30+
@click="groupCtrl.addRule(selectedRule)"
31+
class="query-builder-group-slot__rule-adding-button"
32+
>
33+
Add Rule
34+
</button>
35+
<div class="query-builder-group-slot__spacer"/>
36+
<button
37+
@click="groupCtrl.newGroup"
38+
class="query-builder-group-slot__group-adding-button"
39+
>
40+
Add Group
41+
</button>
42+
</div>
43+
</template>
44+
45+
<style lang="scss" scoped>
46+
.query-builder-group-slot__group-control {
47+
padding: 16px;
48+
display: flex;
49+
flex-direction: row;
50+
}
51+
52+
.query-builder-group-slot__rule-selection,
53+
.query-builder-group-slot__rule-adding-button {
54+
margin-left: 8px;
55+
}
56+
57+
.query-builder-group-slot__spacer {
58+
width: 0;
59+
margin-left: 12px;
60+
margin-right: 12px;
61+
border-left: 1px solid hsl(0, 0%, 75%);
62+
}
63+
</style>

dev/Input.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script lang="ts">
2+
import { Vue, Component, Prop } from 'vue-property-decorator';
3+
4+
@Component({
5+
model: {
6+
event: 'input',
7+
prop: 'value',
8+
},
9+
})
10+
export default class Input extends Vue {
11+
@Prop({
12+
type: String,
13+
default: '',
14+
}) readonly value!: string;
15+
16+
get model() {
17+
return this.value;
18+
}
19+
20+
set model(value: string) {
21+
this.$emit('input', value);
22+
}
23+
}
24+
</script>
25+
26+
<template>
27+
<input
28+
type="text"
29+
v-model="model"
30+
placeholder="dummy input"
31+
>
32+
</template>

dev/Number.vue

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script lang="ts">
2+
import { Vue, Component, Prop } from 'vue-property-decorator';
3+
4+
@Component({
5+
model: {
6+
event: 'input',
7+
prop: 'value',
8+
},
9+
})
10+
export default class Input extends Vue {
11+
@Prop({
12+
type: Number,
13+
default: 0,
14+
}) readonly value!: number;
15+
16+
get model() {
17+
return this.value;
18+
}
19+
20+
set model(value: any) {
21+
if (typeof value === 'number') {
22+
this.$emit('input', value);
23+
}
24+
}
25+
}
26+
</script>
27+
28+
<template>
29+
<input
30+
type="number"
31+
v-model.number="model"
32+
placeholder="dummy number"
33+
>
34+
</template>

dev/RuleSlot.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<script lang="ts">
2+
import { Component, Vue, Prop } from 'vue-property-decorator';
3+
import { RuleSlotProps } from '@/types';
4+
5+
@Component
6+
export default class RuleSlot extends Vue {
7+
@Prop({ required: true }) readonly ruleCtrl!: RuleSlotProps
8+
9+
get ruleData(): any {
10+
return this.ruleCtrl.ruleData;
11+
}
12+
13+
set ruleData(newData: any) {
14+
this.ruleCtrl.updateRuleData(newData);
15+
}
16+
}
17+
</script>
18+
19+
<template>
20+
<div>
21+
<span class="slot-text">SLOT #rule</span>
22+
<component
23+
:is="ruleCtrl.ruleComponent"
24+
v-model="ruleData"
25+
/>
26+
</div>
27+
</template>
28+
29+
<style lang="scss" scoped>
30+
.slot-text {
31+
margin-right: 8px;
32+
}
33+
</style>

src/main.ts renamed to dev/main.ts

File renamed without changes.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "query-builder",
33
"version": "0.1.0",
4+
"main": "./dist/query-builder.common.js",
45
"private": true,
56
"scripts": {
6-
"serve": "vue-cli-service serve",
7-
"build": "vue-cli-service build",
7+
"serve": "vue-cli-service serve dev/main.ts",
8+
"build": "vue-cli-service build --target lib src/QueryBuilder.vue",
89
"test:unit": "vue-cli-service test:unit",
9-
"lint": "vue-cli-service lint"
10+
"lint": "vue-cli-service lint src/ tests/ dev/"
1011
},
1112
"dependencies": {
1213
"@types/sortablejs": "^1.10.2",

public/favicon.ico

-4.19 KB
Binary file not shown.

public/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
<meta charset="utf-8">
55
<meta http-equiv="X-UA-Compatible" content="IE=edge">
66
<meta name="viewport" content="width=device-width,initial-scale=1.0">
7-
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
87
<title>query-builder</title>
98
</head>
109
<body>

0 commit comments

Comments
 (0)