Skip to content

Commit af3d741

Browse files
Merge pull request #185 from appwrite/fix-4762-index-creation-preview-values
fix: createIndex attribute select changing all other selects
2 parents a31f099 + 322f9e3 commit af3d741

File tree

2 files changed

+73
-105
lines changed
  • src
    • lib/helpers
    • routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes

2 files changed

+73
-105
lines changed

src/lib/helpers/array.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export function intersection(arr1: unknown[], arr2: unknown[]) {
33
const intersection = new Set(arr1.filter((elem) => set.has(elem)));
44
return Array.from(intersection);
55
}
6+
67
export function difference(arr1: unknown[], arr2: unknown[]) {
78
const set = new Set(arr2);
89
const intersection = new Set(arr1.filter((elem) => !set.has(elem)));
@@ -12,3 +13,17 @@ export function difference(arr1: unknown[], arr2: unknown[]) {
1213
export function symmetricDifference(arr1: unknown[], arr2: unknown[]) {
1314
return difference(arr1, arr2).concat(difference(arr2, arr1));
1415
}
16+
17+
/**
18+
* Removes the element at the specified index from the array, and returns a new array.
19+
*
20+
* @export
21+
* @template T
22+
* @param {T[]} arr
23+
* @param {number} index
24+
* @returns {T[]}
25+
*/
26+
export function remove<T>(arr: T[], index: number): T[] {
27+
// Remove the element at the given index, return a new array
28+
return [...arr.slice(0, index), ...arr.slice(index + 1)];
29+
}

src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte

Lines changed: 58 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import { Dependencies } from '$lib/constants';
1212
import Select from './select.svelte';
1313
import { trackEvent } from '$lib/actions/analytics';
14+
import { remove } from '$lib/helpers/array';
1415
1516
export let showCreateIndex = false;
1617
export let externalAttribute: Attributes = null;
@@ -24,115 +25,77 @@
2425
{ value: 'unique', label: 'Unique' },
2526
{ value: 'fulltext', label: 'FullText' }
2627
];
27-
let newAttr = false;
2828
let selectedType = 'key';
29-
$: attributeOptions = $collection.attributes.map((attribute: Attributes) => ({
29+
30+
let attributeOptions = $collection.attributes.map((attribute: Attributes) => ({
3031
value: attribute.key,
3132
label: attribute.key
3233
}));
33-
$: attributeList = [];
34+
let attributeList = [{ value: '', order: '' }];
3435
35-
let selectedAttribute = '';
36-
let selectedOrder = '';
36+
$: addAttributeDisabled = !attributeList.at(-1)?.value || !attributeList.at(-1)?.order;
3737
3838
onMount(() => {
39-
if (externalAttribute) {
40-
attributeList = [{ value: externalAttribute.key, order: 'ASC' }];
41-
}
39+
if (!externalAttribute) return;
40+
attributeList = [{ value: externalAttribute.key, order: 'ASC' }];
4241
});
4342
4443
$: if (showCreateIndex) {
45-
attributeList = [];
46-
selectedOrder = selectedAttribute = '';
44+
attributeList = [{ value: '', order: '' }];
4745
selectedType = 'key';
4846
key = null;
4947
}
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-
}
7748
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 {
7876
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+
}
8186
</script>
8287

83-
<Modal bind:error size="big" on:submit={created} bind:show={showCreateIndex}>
88+
<Modal bind:error size="big" on:submit={create} bind:show={showCreateIndex}>
8489
<svelte:fragment slot="header">Create Index</svelte:fragment>
8590
<FormList>
8691
<InputText id="key" label="Index Key" placeholder="Enter Key" bind:value={key} autofocus />
8792
<InputSelect options={types} id="type" label="Index type" bind:value={selectedType} />
8893

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}
13295
<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>
13699

137100
<optgroup label="Internal">
138101
<option value="$id">$id</option>
@@ -141,46 +104,36 @@
141104
</optgroup>
142105
<optgroup label="Attributes">
143106
{#each attributeOptions as option}
144-
<option
145-
value={option.value}
146-
selected={option.value === selectedAttribute}>
107+
<option value={option.value}>
147108
{option.label}
148109
</option>
149110
{/each}
150111
</optgroup>
151112
</Select>
152113
</div>
153114
<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>
156117

157118
<option value="ASC"> ASC </option>
158119
<option value="DESC"> DESC </option>
159120
</Select>
160121
</div>
122+
161123
<div class="form-item-part u-cross-child-end">
162124
<Button
163125
text
164-
disabled={false}
126+
disabled={attributeList.length <= 1}
165127
on:click={() => {
166-
newAttr = false;
167-
selectedAttribute = selectedOrder = '';
128+
attributeList = remove(attributeList, i);
168129
}}>
169130
<span class="icon-x" aria-hidden="true" />
170131
</Button>
171132
</div>
172133
</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}>
184137
<span class="icon-plus" aria-hidden="true" />
185138
<span class="text">Add attribute</span>
186139
</Button>

0 commit comments

Comments
 (0)