|
11 | 11 | import { Dependencies } from '$lib/constants';
|
12 | 12 | import Select from './select.svelte';
|
13 | 13 | import { trackEvent } from '$lib/actions/analytics';
|
| 14 | + import { remove } from '$lib/helpers/array'; |
14 | 15 |
|
15 | 16 | export let showCreateIndex = false;
|
16 | 17 | export let externalAttribute: Attributes = null;
|
|
24 | 25 | { value: 'unique', label: 'Unique' },
|
25 | 26 | { value: 'fulltext', label: 'FullText' }
|
26 | 27 | ];
|
27 |
| - let newAttr = false; |
28 | 28 | let selectedType = 'key';
|
29 |
| - $: attributeOptions = $collection.attributes.map((attribute: Attributes) => ({ |
| 29 | +
|
| 30 | + let attributeOptions = $collection.attributes.map((attribute: Attributes) => ({ |
30 | 31 | value: attribute.key,
|
31 | 32 | label: attribute.key
|
32 | 33 | }));
|
33 |
| - $: attributeList = []; |
| 34 | + let attributeList = [{ value: '', order: '' }]; |
34 | 35 |
|
35 |
| - let selectedAttribute = ''; |
36 |
| - let selectedOrder = ''; |
| 36 | + $: addAttributeDisabled = !attributeList.at(-1)?.value || !attributeList.at(-1)?.order; |
37 | 37 |
|
38 | 38 | onMount(() => {
|
39 |
| - if (externalAttribute) { |
40 |
| - attributeList = [{ value: externalAttribute.key, order: 'ASC' }]; |
41 |
| - } |
| 39 | + if (!externalAttribute) return; |
| 40 | + attributeList = [{ value: externalAttribute.key, order: 'ASC' }]; |
42 | 41 | });
|
43 | 42 |
|
44 | 43 | $: if (showCreateIndex) {
|
45 |
| - attributeList = []; |
46 |
| - selectedOrder = selectedAttribute = ''; |
| 44 | + attributeList = [{ value: '', order: '' }]; |
47 | 45 | selectedType = 'key';
|
48 | 46 | key = null;
|
49 | 47 | }
|
50 |
| - const created = async () => { |
51 |
| - if (key && selectedAttribute && selectedOrder && selectedType) { |
52 |
| - if (selectedAttribute && selectedOrder) { |
53 |
| - attributeList.push({ value: selectedAttribute, order: selectedOrder }); |
54 |
| - selectedAttribute = selectedOrder = ''; |
55 |
| - } |
56 |
| - try { |
57 |
| - await sdkForProject.databases.createIndex( |
58 |
| - databaseId, |
59 |
| - $collection.$id, |
60 |
| - key, |
61 |
| - selectedType, |
62 |
| - attributeList.map((a) => a.value), |
63 |
| - attributeList.map((a) => a.order) |
64 |
| - ); |
65 |
| - invalidate(Dependencies.COLLECTION); |
66 |
| - addNotification({ |
67 |
| - message: 'Index has been created', |
68 |
| - type: 'success' |
69 |
| - }); |
70 |
| - trackEvent('submit_index_create'); |
71 |
| - } catch (error) { |
72 |
| - addNotification({ |
73 |
| - message: error.message, |
74 |
| - type: 'error' |
75 |
| - }); |
76 |
| - } |
77 | 48 |
|
| 49 | + async function create() { |
| 50 | + if (!(key && selectedType && !addAttributeDisabled)) { |
| 51 | + error = 'All fields are required'; |
| 52 | + return; |
| 53 | + } |
| 54 | +
|
| 55 | + try { |
| 56 | + await sdkForProject.databases.createIndex( |
| 57 | + databaseId, |
| 58 | + $collection.$id, |
| 59 | + key, |
| 60 | + selectedType, |
| 61 | + attributeList.map((a) => a.value), |
| 62 | + attributeList.map((a) => a.order) |
| 63 | + ); |
| 64 | + invalidate(Dependencies.COLLECTION); |
| 65 | + addNotification({ |
| 66 | + message: 'Index has been created', |
| 67 | + type: 'success' |
| 68 | + }); |
| 69 | + trackEvent('submit_index_create'); |
| 70 | + } catch (error) { |
| 71 | + addNotification({ |
| 72 | + message: error.message, |
| 73 | + type: 'error' |
| 74 | + }); |
| 75 | + } finally { |
78 | 76 | showCreateIndex = false;
|
79 |
| - } else error = 'All fields are required'; |
80 |
| - }; |
| 77 | + } |
| 78 | + } |
| 79 | +
|
| 80 | + function addAttribute() { |
| 81 | + if (addAttributeDisabled) return; |
| 82 | +
|
| 83 | + // We assign instead of pushing to trigger Svelte's reactivity |
| 84 | + attributeList = [...attributeList, { value: '', order: '' }]; |
| 85 | + } |
81 | 86 | </script>
|
82 | 87 |
|
83 |
| -<Modal bind:error size="big" on:submit={created} bind:show={showCreateIndex}> |
| 88 | +<Modal bind:error size="big" on:submit={create} bind:show={showCreateIndex}> |
84 | 89 | <svelte:fragment slot="header">Create Index</svelte:fragment>
|
85 | 90 | <FormList>
|
86 | 91 | <InputText id="key" label="Index Key" placeholder="Enter Key" bind:value={key} autofocus />
|
87 | 92 | <InputSelect options={types} id="type" label="Index type" bind:value={selectedType} />
|
88 | 93 |
|
89 |
| - {#if attributeList?.length} |
90 |
| - {#each attributeList as index, i} |
91 |
| - <li class="form-item is-multiple"> |
92 |
| - <div class="form-item-part u-stretch"> |
93 |
| - <Select id="attribute" label="Attribute" bind:value={index.value}> |
94 |
| - <optgroup label="Internal"> |
95 |
| - <option value="$id">$id</option> |
96 |
| - <option value="$createdAt">$createdAt</option> |
97 |
| - <option value="$updatedAt">$updatedAt</option> |
98 |
| - </optgroup> |
99 |
| - <optgroup label="Attributes"> |
100 |
| - {#each attributeOptions as option} |
101 |
| - <option |
102 |
| - value={option.value} |
103 |
| - selected={option.value === selectedAttribute}> |
104 |
| - {option.label} |
105 |
| - </option> |
106 |
| - {/each} |
107 |
| - </optgroup> |
108 |
| - </Select> |
109 |
| - </div> |
110 |
| - <div class="form-item-part u-stretch"> |
111 |
| - <Select id="order" label="Order" bind:value={index.order}> |
112 |
| - <option value="ASC"> ASC </option> |
113 |
| - <option value="DESC"> DESC </option> |
114 |
| - </Select> |
115 |
| - </div> |
116 |
| - |
117 |
| - <div class="form-item-part u-cross-child-end"> |
118 |
| - <Button |
119 |
| - text |
120 |
| - disabled={externalAttribute && i === 0} |
121 |
| - on:click={() => { |
122 |
| - if (i === 0) attributeList = []; |
123 |
| - attributeList = attributeList.splice(i, 1); |
124 |
| - }}> |
125 |
| - <span class="icon-x" aria-hidden="true" /> |
126 |
| - </Button> |
127 |
| - </div> |
128 |
| - </li> |
129 |
| - {/each} |
130 |
| - {/if} |
131 |
| - {#if !attributeList?.length || newAttr} |
| 94 | + {#each attributeList as attribute, i} |
132 | 95 | <li class="form-item is-multiple">
|
133 |
| - <div class="form-item-part u-stretch" style="align-items: flex-start;"> |
134 |
| - <Select id="attribute" label="Attribute" bind:value={selectedAttribute}> |
135 |
| - <option value="" disabled selected hidden>Select Attribute</option> |
| 96 | + <div class="form-item-part u-stretch"> |
| 97 | + <Select id={`attribute-${i}`} label="Attribute" bind:value={attribute.value}> |
| 98 | + <option value="" disabled hidden>Select Attribute</option> |
136 | 99 |
|
137 | 100 | <optgroup label="Internal">
|
138 | 101 | <option value="$id">$id</option>
|
|
141 | 104 | </optgroup>
|
142 | 105 | <optgroup label="Attributes">
|
143 | 106 | {#each attributeOptions as option}
|
144 |
| - <option |
145 |
| - value={option.value} |
146 |
| - selected={option.value === selectedAttribute}> |
| 107 | + <option value={option.value}> |
147 | 108 | {option.label}
|
148 | 109 | </option>
|
149 | 110 | {/each}
|
150 | 111 | </optgroup>
|
151 | 112 | </Select>
|
152 | 113 | </div>
|
153 | 114 | <div class="form-item-part u-stretch">
|
154 |
| - <Select id="order" label="Order" bind:value={selectedOrder}> |
155 |
| - <option value="" disabled selected hidden>Select Order</option> |
| 115 | + <Select id={`order-${i}`} label="Order" bind:value={attribute.order}> |
| 116 | + <option value="" disabled hidden>Select Order</option> |
156 | 117 |
|
157 | 118 | <option value="ASC"> ASC </option>
|
158 | 119 | <option value="DESC"> DESC </option>
|
159 | 120 | </Select>
|
160 | 121 | </div>
|
| 122 | + |
161 | 123 | <div class="form-item-part u-cross-child-end">
|
162 | 124 | <Button
|
163 | 125 | text
|
164 |
| - disabled={false} |
| 126 | + disabled={attributeList.length <= 1} |
165 | 127 | on:click={() => {
|
166 |
| - newAttr = false; |
167 |
| - selectedAttribute = selectedOrder = ''; |
| 128 | + attributeList = remove(attributeList, i); |
168 | 129 | }}>
|
169 | 130 | <span class="icon-x" aria-hidden="true" />
|
170 | 131 | </Button>
|
171 | 132 | </div>
|
172 | 133 | </li>
|
173 |
| - {/if} |
174 |
| - <Button |
175 |
| - text |
176 |
| - noMargin |
177 |
| - on:click={() => { |
178 |
| - newAttr = true; |
179 |
| - if (selectedAttribute && selectedOrder) { |
180 |
| - attributeList.push({ value: selectedAttribute, order: selectedOrder }); |
181 |
| - selectedAttribute = selectedOrder = ''; |
182 |
| - } |
183 |
| - }}> |
| 134 | + {/each} |
| 135 | + |
| 136 | + <Button text noMargin on:click={addAttribute} disabled={addAttributeDisabled}> |
184 | 137 | <span class="icon-plus" aria-hidden="true" />
|
185 | 138 | <span class="text">Add attribute</span>
|
186 | 139 | </Button>
|
|
0 commit comments