Skip to content

Commit

Permalink
Recording List in Spectrogram Annotator (#48)
Browse files Browse the repository at this point in the history
* initial annotation-recording list

* removing uneeded code from recording list

* add in next button as well as global shared ref for recordings
  • Loading branch information
BryonLewis authored Feb 23, 2024
1 parent 46493c7 commit 7a6fb01
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 27 deletions.
64 changes: 57 additions & 7 deletions client/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
<script lang="ts">
import { defineComponent, inject, ref, onMounted } from "vue";
import { defineComponent, inject, ref, onMounted, computed, watch } from "vue";
import OAuthClient from "@girder/oauth-client";
import { useRouter } from "vue-router";
import { useRoute, useRouter } from "vue-router";
import useState from "./use/useState";
import { getRecordings } from "./api/api";
export default defineComponent({
setup() {
const oauthClient = inject<OAuthClient>("oauthClient");
const router = useRouter();
const route = useRoute();
const { nextShared, sharedList } = useState();
const getShared = async () => {
sharedList.value = (await getRecordings(true)).data;
};
if (sharedList.value.length === 0) {
getShared();
}
if (oauthClient === undefined) {
throw new Error('Must provide "oauthClient" into component.');
}
const loginText = ref('Login');
const loginText = ref("Login");
const checkLogin = () => {
if (oauthClient.isLoggedIn) {
loginText.value = "Logout";
Expand All @@ -32,8 +42,20 @@ export default defineComponent({
onMounted(() => {
checkLogin();
});
const activeTab = ref("recordings");
return { oauthClient, loginText, logInOrOut, activeTab };
router.afterEach((guard) => {
if (guard.path.includes("spectrogram")) {
activeTab.value = "spectrogram";
}
});
const activeTab = ref(route.path.includes("spectrogram") ? "spectrogram" : "recordings");
const containsSpectro = computed(() => route.path.includes("spectrogram"));
watch(containsSpectro, () => {
if (route.path.includes("spectrogram")) {
activeTab.value = "spectrogram";
}
});
return { oauthClient, containsSpectro, loginText, logInOrOut, activeTab, nextShared };
},
});
</script>
Expand All @@ -42,9 +64,9 @@ export default defineComponent({
<v-app id="app">
<v-app-bar app>
<v-tabs
v-if="oauthClient.isLoggedIn"
v-if="oauthClient.isLoggedIn && activeTab"
v-model="activeTab"
fixed-tabs
:model-value="activeTab"
>
<v-tab
to="/"
Expand All @@ -58,8 +80,36 @@ export default defineComponent({
>
Recordings
</v-tab>
<v-tab
v-show="containsSpectro"
value="spectrogram"
>
Spectrogram
</v-tab>
</v-tabs>
<v-spacer />
<v-tooltip
v-if="containsSpectro && nextShared !== false"
bottom
>
<template #activator="{ props: subProps }">
<v-btn
v-bind="subProps"
variant="outlined"
:to="`/recording/${nextShared.id}/spectrogram`"
>
Next Shared<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<span v-if="nextShared">
<div>
<b>Name:</b><span>{{ nextShared.name }}</span>
</div>
<div>
<b>Owner:</b><span>{{ nextShared.owner_username }}</span>
</div>
</span>
</v-tooltip>
<v-btn @click="logInOrOut">
{{ loginText }}
</v-btn>
Expand Down
52 changes: 38 additions & 14 deletions client/src/components/AnnotationList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { defineComponent, PropType } from "vue";
import { SpectroInfo } from './geoJS/geoJSUtils';
import useState from "../use/useState";
import { watch, ref } from "vue";
import RecordingList from "./RecordingList.vue";
export default defineComponent({
name: "AnnotationList",
components: {
RecordingList,
},
props: {
spectroInfo: {
Expand Down Expand Up @@ -36,9 +38,13 @@ export default defineComponent({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tabSwitch = (event: any) => {
// On tab switches we want to deselect the curret anntation
tab.value = event as 'sequence' | 'pulse';
selectedType.value = event as 'sequence' | 'pulse';
selectedId.value = null;
if (['sequence', 'pulse'].includes(event)) {
tab.value = event as 'sequence' | 'pulse';
selectedType.value = event as 'sequence' | 'pulse';
selectedId.value = null;
} else {
tab.value = 'recordings';
}
};
return {
Expand All @@ -60,20 +66,38 @@ export default defineComponent({
<template>
<v-card class="pa-0 ma-0">
<v-card-title>
<v-tabs
v-model="tab"
@update:model-value="tabSwitch($event)"
>
<v-tab value="pulse">
Pulse
</v-tab>
<v-tab value="sequence">
Sequence
</v-tab>
</v-tabs>
<v-row dense>
<v-tabs
v-model="tab"
class="ma-auto"
@update:model-value="tabSwitch($event)"
>
<v-tab
value="recordings"
size="x-small"
>
Recordings
</v-tab>
<v-tab
value="pulse"
size="x-small"
>
Pulse
</v-tab>
<v-tab
value="sequence"
size="x-small"
>
Sequence
</v-tab>
</v-tabs>
</v-row>
</v-card-title>
<v-card-text class="">
<v-window v-model="tab">
<v-window-item value="recordings">
<recording-list />
</v-window-item>
<v-window-item value="pulse">
<v-row class="pa-2">
<v-col>
Expand Down
171 changes: 171 additions & 0 deletions client/src/components/RecordingList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<script lang="ts">
import { defineComponent, ref, Ref, onMounted, computed } from 'vue';
import { getRecordings } from '../api/api';
import useState from '../use/useState';
import { EditingRecording } from './UploadRecording.vue';
export default defineComponent({
components: {
},
setup() {
const { sharedList, recordingList } = useState();
const editingRecording: Ref<EditingRecording | null> = ref(null);
const fetchRecordings = async () => {
const recordings = await getRecordings();
recordingList.value = recordings.data;
const shared = await getRecordings(true);
sharedList.value = shared.data;
};
onMounted(() => fetchRecordings());
const openPanel = ref(1);
const filtered = ref(true);
const modifiedList = computed(() => {
if (filtered.value) {
return sharedList.value.filter((item) => !item.userMadeAnnotations);
}
return sharedList.value;
});
return {
recordingList,
sharedList,
modifiedList,
filtered,
editingRecording,
openPanel,
};
},
});
</script>

<template>
<v-expansion-panels v-model="openPanel">
<v-expansion-panel>
<v-expansion-panel-title>My Recordings</v-expansion-panel-title>
<v-expansion-panel-text>
<div>
<v-row
dense
class="text-center"
>
<v-col class="text-left">
<b>Name</b>
</v-col>
<v-col><b>Public</b></v-col>
<v-col><b>Annotations</b></v-col>
</v-row>
</div>
<div
v-for="item in recordingList"
:key="`public_${item.id}`"
>
<v-row
dense
class="text-center"
>
<v-col class="text-left">
<router-link
:to="`/recording/${item.id.toString()}/spectrogram`"
>
{{ item.name }}
</router-link>
</v-col>
<v-col>
<v-icon
v-if="item.public"
color="success"
>
mdi-check
</v-icon>
<v-icon
v-else
color="error"
>
mdi-close
</v-icon>
</v-col>
<v-col>
<div>
{{ item.userAnnotations }}
</div>
</v-col>
</v-row>
</div>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel-title>Public</v-expansion-panel-title>
<v-expansion-panel-text class="ma-0 pa-0">
<v-switch
v-model="filtered"
label="Filter Annotated"
dense
/>
<div>
<v-row
dense
class="text-center"
>
<v-col class="text-left">
<b>Name</b>
</v-col>
<v-col><b>Owner</b></v-col>
<v-col><b>Annotated</b></v-col>
</v-row>
</div>
<div
v-for="item in modifiedList"
:key="`public_${item.id}`"
>
<v-row
dense
class="text-center"
>
<v-col class="text-left">
<router-link
:to="`/recording/${item.id.toString()}/spectrogram`"
>
{{ item.name }}
</router-link>
</v-col>
<v-col>
<div style="font-size:0.75em">
{{ item.owner_username }}
</div>
</v-col>
<v-col>
<div>
<v-icon
v-if="item.userMadeAnnotations"
color="success"
>
mdi-check
</v-icon>
<v-icon
v-else
color="error"
>
mdi-close
</v-icon>
</div>
</v-col>
</v-row>
</div>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</template>

<style scoped>
.v-expansion-panel-text>>> .v-expansion-panel-text__wrap {
padding: 0 !important;
}
.v-expansion-panel-text__wrapper {
padding: 0 !important;
}
</style>
Loading

0 comments on commit 7a6fb01

Please sign in to comment.