Skip to content

Commit 7ca0ef4

Browse files
authored
Merge pull request #26 from Mosquito-Alert/add_search_bar
Added search bar for identification task and annotation ListView
2 parents f5ff7aa + e1b2cfa commit 7ca0ef4

File tree

7 files changed

+281
-250
lines changed

7 files changed

+281
-250
lines changed

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"@websitebeaver/vue-magnifier": "^1.1.0",
2323
"dayjs": "^1.11.13",
2424
"exifr": "^7.1.3",
25-
"mosquito-alert": "github:mosquito-alert/mosquito-alert-typescript-sdk#0.1.23",
25+
"mosquito-alert": "github:mosquito-alert/mosquito-alert-typescript-sdk#0.1.24",
2626
"pinia": "^3.0.1",
2727
"primeicons": "^7.0.0",
2828
"primevue": "^4.3.3",

src/components/annotations/AnnotationDataTable.vue

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,70 @@
11
<template>
2-
<DataTable :value="annotations" ref="dt" stripedRows :loading="loading" data-key="id" class="overflow-y-auto">
3-
<Column header="Observation UUID">
4-
<template #body="slotProps">
5-
<Button asChild variant="link">
6-
<RouterLink
7-
:to="{ name: 'identification_task', params: { observationUuid: slotProps.data.observation_uuid } }" custom
8-
v-slot="{ href }">
9-
<a :href="href" target="_blank" class="flex items-center gap-2">
10-
<span class="hover:underline">{{ slotProps.data.observation_uuid }}</span>
11-
<i class="pi pi-external-link" style="font-size: 0.8rem" />
12-
</a>
13-
</RouterLink>
14-
</Button>
15-
</template>
16-
</Column>
17-
<Column header="Type">
18-
<template #body="slotProps">
19-
<AnnotationTypeTag :type="slotProps.data.type" />
20-
</template>
21-
</Column>
22-
<Column header="Best image">
23-
<template #body="slotProps">
24-
<Image v-if="slotProps.data.best_photo" :src="`${slotProps.data.best_photo.url}`" preview
25-
imageClass="aspect-square object-cover rounded w-16" />
26-
</template>
27-
</Column>
2+
<div class="flex-1 h-full overflow-hidden flex border border-surface rounded-2xl">
3+
<DataTable :value="annotations" ref="dt" stripedRows :loading="loading" data-key="id" class="overflow-y-auto" :pt="{
4+
root: {
5+
class: 'w-full flex-1 overflow-x-auto'
6+
},
7+
}">
8+
<Column header="Observation UUID">
9+
<template #body="slotProps">
10+
<Button asChild variant="link">
11+
<RouterLink
12+
:to="{ name: 'identification_task', params: { observationUuid: slotProps.data.observation_uuid } }" custom
13+
v-slot="{ href }">
14+
<a :href="href" target="_blank" class="flex items-center gap-2">
15+
<span class="hover:underline">{{ slotProps.data.observation_uuid }}</span>
16+
<i class="pi pi-external-link" style="font-size: 0.8rem" />
17+
</a>
18+
</RouterLink>
19+
</Button>
20+
</template>
21+
</Column>
22+
<Column header="Type">
23+
<template #body="slotProps">
24+
<AnnotationTypeTag :type="slotProps.data.type" />
25+
</template>
26+
</Column>
27+
<Column header="Best image">
28+
<template #body="slotProps">
29+
<Image v-if="slotProps.data.best_photo" :src="`${slotProps.data.best_photo.url}`" preview
30+
imageClass="aspect-square object-cover rounded w-16" />
31+
</template>
32+
</Column>
2833

29-
<Column header="Classification">
30-
<template #body="slotProps">
31-
<TaxonClassificationTag :classification="slotProps.data.classification" />
32-
</template>
33-
</Column>
34-
<Column field="is_flagged" header="Is flagged" dataType="boolean" style="min-width: 6rem">
35-
<template #body="slotProps">
36-
<i class="pi"
37-
:class="{ 'pi-check-circle text-green-500': slotProps.data.is_flagged, 'pi-times-circle text-red-400': !slotProps.data.is_flagged }" />
38-
</template>
39-
</Column>
40-
<!-- <Column field="is_decisive" header="Is executive" dataType="boolean" style="min-width: 6rem">
34+
<Column header="Classification">
35+
<template #body="slotProps">
36+
<TaxonClassificationTag :classification="slotProps.data.classification" />
37+
</template>
38+
</Column>
39+
<Column field="is_flagged" header="Is flagged" dataType="boolean" style="min-width: 6rem">
40+
<template #body="slotProps">
41+
<i class="pi"
42+
:class="{ 'pi-check-circle text-green-500': slotProps.data.is_flagged, 'pi-times-circle text-red-400': !slotProps.data.is_flagged }" />
43+
</template>
44+
</Column>
45+
<!-- <Column field="is_decisive" header="Is executive" dataType="boolean" style="min-width: 6rem">
4146
<template #body="slotProps">
4247
<i class="pi"
4348
:class="{ 'pi-check-circle text-green-500': slotProps.data.is_decisive, 'pi-times-circle text-red-400': !slotProps.data.is_decisive }" />
4449
</template>
4550
</Column> -->
46-
<Column field="is_favourite" header="Is Favourite" dataType="boolean" style="min-width: 6rem">
47-
<template #body="slotProps">
48-
<i class="pi"
49-
:class="{ 'pi-check-circle text-green-500': slotProps.data.observation_flags.is_favourite, 'pi-times-circle text-red-400': !slotProps.data.observation_flags.is_favourite }" />
50-
</template>
51-
</Column>
52-
<Column header="Date">
53-
<template #body="slotProps">
54-
{{ formatLocalDateTime(slotProps.data.updated_at) }}
51+
<Column field="is_favourite" header="Is Favourite" dataType="boolean" style="min-width: 6rem">
52+
<template #body="slotProps">
53+
<i class="pi"
54+
:class="{ 'pi-check-circle text-green-500': slotProps.data.observation_flags.is_favourite, 'pi-times-circle text-red-400': !slotProps.data.observation_flags.is_favourite }" />
55+
</template>
56+
</Column>
57+
<Column header="Date">
58+
<template #body="slotProps">
59+
{{ formatLocalDateTime(slotProps.data.updated_at) }}
60+
</template>
61+
</Column>
62+
<template #expansion="slotProps">
63+
<p><span class="font-bold">Public note: </span>{{ slotProps.data.feedback.public_note }}</p>
64+
<p><span class="font-bold">Internal note: </span>{{ slotProps.data.feedback.internal_note }}</p>
5565
</template>
56-
</Column>
57-
<template #expansion="slotProps">
58-
<p><span class="font-bold">Public note: </span>{{ slotProps.data.feedback.public_note }}</p>
59-
<p><span class="font-bold">Internal note: </span>{{ slotProps.data.feedback.internal_note }}</p>
60-
</template>
61-
</DataTable>
66+
</DataTable>
67+
</div>
6268
</template>
6369

6470

src/components/identificationTasks/IdentificationTaskList.vue

Lines changed: 75 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,88 @@
11
<template>
2-
<DataTable :value="tasks" ref="dt" stripedRows :loading="loading" data-key="observation.uuid">
3-
<!-- <template #header>
2+
<div class="flex-1 h-full overflow-hidden flex border border-surface rounded-2xl">
3+
<DataTable :value="tasks" ref="dt" stripedRows :loading="loading" data-key="observation.uuid" :pt="{
4+
root: {
5+
class: 'w-full flex-1 overflow-x-auto'
6+
},
7+
}">
8+
<!-- <template #header>
49
<div style="text-align:left">
510
<MultiSelect id="column_select" :modelValue="selectedColumns" :options="columns" optionLabel="header"
611
@update:modelValue="onSelectColumn" display="chip" :maxSelectedLabels="0" filter selectedItemsLabel="Columns"
712
placeholder="Columns" />
813
</div>
914
</template> -->
10-
<Column field="observation.uuid" header="UUID">
11-
<template #body="slotProps">
12-
<RouterLink :to="{ name: 'identification_task', params: { observationUuid: slotProps.data.observation.uuid } }"
13-
custom v-slot="{ href }">
14-
<a :href="href" target="_blank" class="flex items-center gap-2">
15-
<span class="hover:underline">{{ slotProps.data.observation.uuid }}</span>
16-
<i class="pi pi-external-link" style="font-size: 0.8rem" />
17-
</a>
18-
</RouterLink>
19-
</template>
20-
</Column>
21-
<Column header="Status">
22-
<template #body="slotProps">
23-
<IdentificationTaskStatusTag :status="slotProps.data.status" />
24-
</template>
25-
</Column>
26-
<Column header="Image">
27-
<template #body="slotProps">
28-
<Image :src="`${slotProps.data.public_photo.url}`" preview
29-
imageClass="aspect-square object-cover rounded w-16" />
30-
</template>
31-
</Column>
32-
<Column header="Taxon">
33-
<template #body="slotProps">
34-
<IdentificationTaskResultTag v-if="slotProps.data.result" :result="slotProps.data.result" />
35-
</template>
36-
</Column>
37-
<Column header="Country">
38-
<template #body="slotProps">
39-
<CountryTag v-if="slotProps.data.observation.location.country"
40-
:country="slotProps.data.observation.location.country" />
41-
</template>
42-
</Column>
43-
<Column header="Assignations">
44-
<template #body="slotProps">
45-
<AvatarGroup>
46-
<UserAvatar v-for="assignment, index in slotProps.data.assignments" :key="index" :user="assignment.user"
47-
v-tooltip.top="assignment.annotation_id === null ? `${assignment.user.full_name || assignment.user.username} (Pending)` : assignment.user.full_name || assignment.user.username"
48-
:class="assignment.annotation_id ? '' : 'border-(--p-tag-warn-color)! bg-(--p-tag-warn-background)! text-(--p-tag-warn-color)!'" />
49-
</AvatarGroup>
50-
</template>
51-
</Column>
52-
<Column field="is_flagged" header="Is flagged" dataType="boolean" style="min-width: 6rem">
53-
<template #body="slotProps">
54-
<i class="pi"
55-
:class="{ 'pi-check-circle text-green-500': slotProps.data.is_flagged, 'pi-times-circle text-red-400': !slotProps.data.is_flagged }" />
56-
</template>
57-
</Column>
58-
<Column field="is_safe" header="Is Safe" dataType="boolean" style="min-width: 6rem">
59-
<template #body="slotProps">
60-
<i v-if='slotProps.data.is_safe' class="pi pi-shield text-green-500" />
61-
</template>
62-
</Column>
63-
<!-- <Column v-for="(col, index) of selectedColumns" :field="col.field" :header="col.header"
15+
<Column field="observation.uuid" header="UUID">
16+
<template #body="slotProps">
17+
<RouterLink
18+
:to="{ name: 'identification_task', params: { observationUuid: slotProps.data.observation.uuid } }" custom
19+
v-slot="{ href }">
20+
<a :href="href" target="_blank" class="flex items-center gap-2">
21+
<span class="hover:underline">{{ slotProps.data.observation.uuid }}</span>
22+
<i class="pi pi-external-link" style="font-size: 0.8rem" />
23+
</a>
24+
</RouterLink>
25+
</template>
26+
</Column>
27+
<Column field="observation.short_id" header="Short ID" />
28+
<Column header="Status">
29+
<template #body="slotProps">
30+
<IdentificationTaskStatusTag :status="slotProps.data.status" />
31+
</template>
32+
</Column>
33+
<Column header="Image">
34+
<template #body="slotProps">
35+
<Image :src="`${slotProps.data.public_photo.url}`" preview
36+
imageClass="aspect-square object-cover rounded w-16" />
37+
</template>
38+
</Column>
39+
<Column header="Taxon">
40+
<template #body="slotProps">
41+
<IdentificationTaskResultTag v-if="slotProps.data.result" :result="slotProps.data.result" />
42+
</template>
43+
</Column>
44+
<Column header="Country">
45+
<template #body="slotProps">
46+
<CountryTag v-if="slotProps.data.observation.location.country"
47+
:country="slotProps.data.observation.location.country" />
48+
</template>
49+
</Column>
50+
<Column header="Assignations">
51+
<template #body="slotProps">
52+
<AvatarGroup>
53+
<UserAvatar v-for="assignment, index in slotProps.data.assignments" :key="index" :user="assignment.user"
54+
v-tooltip.top="assignment.annotation_id === null ? `${assignment.user.full_name || assignment.user.username} (Pending)` : assignment.user.full_name || assignment.user.username"
55+
:class="assignment.annotation_id ? '' : 'border-(--p-tag-warn-color)! bg-(--p-tag-warn-background)! text-(--p-tag-warn-color)!'" />
56+
</AvatarGroup>
57+
</template>
58+
</Column>
59+
<Column field="is_flagged" header="Is flagged" dataType="boolean" style="min-width: 6rem">
60+
<template #body="slotProps">
61+
<i class="pi"
62+
:class="{ 'pi-check-circle text-green-500': slotProps.data.is_flagged, 'pi-times-circle text-red-400': !slotProps.data.is_flagged }" />
63+
</template>
64+
</Column>
65+
<Column field="is_safe" header="Is Safe" dataType="boolean" style="min-width: 6rem">
66+
<template #body="slotProps">
67+
<i v-if='slotProps.data.is_safe' class="pi pi-shield text-green-500" />
68+
</template>
69+
</Column>
70+
<!-- <Column v-for="(col, index) of selectedColumns" :field="col.field" :header="col.header"
6471
:key="col.field + '_' + index">
6572
</Column> -->
6673

67-
<Column header="Created at">
68-
<template #body="slotProps">
69-
{{ formatLocalDateTime(slotProps.data.created_at) }}
70-
</template>
71-
</Column>
72-
<Column header="Last updated">
73-
<template #body="slotProps">
74-
{{ formatLocalDateTime(slotProps.data.updated_at) }}
75-
</template>
76-
</Column>
77-
</DataTable>
74+
<Column header="Created at">
75+
<template #body="slotProps">
76+
{{ formatLocalDateTime(slotProps.data.created_at) }}
77+
</template>
78+
</Column>
79+
<Column header="Last updated">
80+
<template #body="slotProps">
81+
{{ formatLocalDateTime(slotProps.data.updated_at) }}
82+
</template>
83+
</Column>
84+
</DataTable>
85+
</div>
7886
</template>
7987

8088

src/components/observations/ObservationInfoData.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
{{ observation.uuid }}
77
</div>
88
</li>
9+
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
10+
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Short ID</div>
11+
<div class="text-surface-900 dark:text-surface-0 w-full md:w-10/12 md:order-none order-1">
12+
{{ observation.short_id }}
13+
</div>
14+
</li>
915
<li class="flex items-center py-4 px-2 border-t border-surface flex-wrap">
1016
<div class="text-surface-500 dark:text-surface-300 w-6/12 md:w-2/12 font-medium">Created at
1117
</div>

0 commit comments

Comments
 (0)