Skip to content

Commit

Permalink
- Add validation and reset improvements for project labels/tags.
Browse files Browse the repository at this point in the history
- Use mobile friendly card/table templates for managing project labels.
  • Loading branch information
hardiesoft committed Feb 11, 2025
1 parent 029f8cf commit 750f431
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 31 deletions.
1 change: 1 addition & 0 deletions browse-next/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare module 'vue' {
BForm: typeof import('bootstrap-vue-next')['BForm']
BFormCheckbox: typeof import('bootstrap-vue-next')['BFormCheckbox']
BFormCheckboxGroup: typeof import('bootstrap-vue-next')['BFormCheckboxGroup']
BFormFloatingLabel: typeof import('bootstrap-vue-next')['BFormFloatingLabel']
BFormGroup: typeof import('bootstrap-vue-next')['BFormGroup']
BFormInput: typeof import('bootstrap-vue-next')['BFormInput']
BFormInvalidFeedback: typeof import('bootstrap-vue-next')['BFormInvalidFeedback']
Expand Down
2 changes: 2 additions & 0 deletions browse-next/src/components/OverflowingTabList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ const findSelectedItemName = () => {
};
const activeItemTitle = ref<string>("");
// TODO: If overflowing items are selected, move the ellipsis around and have the selected item showing?
</script>

<template>
Expand Down
131 changes: 104 additions & 27 deletions browse-next/src/views/ManageProjectLabelSettingsSubView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,37 @@ const pendingDescription = ref<string>("");
const addPendingCameraLabel = async () => {
if (pendingLabel.value.length) {
await addCameraLabel(pendingLabel.value, pendingDescription.value);
pendingLabel.value = "";
pendingDescription.value = "";
reset();
}
};
const addPendingAudioLabel = async () => {
if (pendingLabel.value.length) {
await addAudioLabel(pendingLabel.value, pendingDescription.value);
pendingLabel.value = "";
pendingDescription.value = "";
reset();
}
};
const canReset = (
labels: RecordingLabel[],
defaultLabels: RecordingLabel[]
) => {
if (labels.length !== defaultLabels.length) {
return true;
}
for (let i = 0; i < labels.length; i++) {
if (labels[i].value !== defaultLabels[i].value) {
return true;
}
}
return false;
};
const reset = () => {
pendingLabel.value = "";
pendingDescription.value = "";
};
// If there are no custom tags, display the defaultTags here in the default order.
// Add tag. delete tag, move tag up, move tag down, reset to defaults
</script>
Expand All @@ -180,6 +198,7 @@ const addPendingAudioLabel = async () => {
project.
</p>
</div>
<hr class="mt-4" />
<div
class="d-flex flex-column flex-md-row justify-content-md-between mb-3 align-items-center"
>
Expand All @@ -195,20 +214,39 @@ const addPendingAudioLabel = async () => {
<button
type="button"
class="btn btn-outline-danger ms-2"
:disabled="
!canReset(localCameraLabels, DEFAULT_CAMERA_RECORDING_LABELS)
"
@click.stop.prevent="resetCameraLabels"
>
Reset
</button>
</div>
</div>
<card-table :items="cameraLabelTableItems" compact :max-card-width="0">
<card-table :items="cameraLabelTableItems" compact :max-card-width="575">
<template #_deleteAction="{ cell }">
<button class="btn" @click.prevent="() => removeCameraLabel(cell.value)">
<font-awesome-icon icon="trash-can" />
</button>
</template>
<template #card="{ card }">
<div class="d-flex flex-row">
<div class="d-flex flex-column flex-grow-1 me-3">
<span
><strong>{{ card.label.value }}</strong></span
>
<span>{{ card.description.value }}</span>
</div>
<button
class="btn"
@click.prevent="() => removeCameraLabel(card.label.value)"
>
<font-awesome-icon icon="trash-can" />
</button>
</div>
</template>
</card-table>

<hr class="mt-4" />
<div
class="d-flex flex-column flex-md-row justify-content-md-between my-3 align-items-center"
>
Expand All @@ -225,52 +263,91 @@ const addPendingAudioLabel = async () => {
type="button"
class="btn btn-outline-danger ms-2"
@click.stop.prevent="resetAudioLabels"
:disabled="!canReset(localAudioLabels, DEFAULT_AUDIO_RECORDING_LABELS)"
>
Reset
</button>
</div>
</div>
<card-table :items="audioLabelTableItems" compact :max-card-width="0">
<card-table :items="audioLabelTableItems" compact :max-card-width="575">
<template #_deleteAction="{ cell }">
<button class="btn" @click.prevent="() => removeAudioLabel(cell.value)">
<font-awesome-icon icon="trash-can" />
</button>
</template>
<template #card="{ card }">
<div class="d-flex flex-row">
<div class="d-flex flex-column flex-grow-1 me-3">
<span
><strong>{{ card.label.value }}</strong></span
>
<span>{{ card.description.value }}</span>
</div>
<button
class="btn"
@click.prevent="() => removeCameraLabel(card.label.value)"
>
<font-awesome-icon icon="trash-can" />
</button>
</div>
</template>
</card-table>
<b-modal
v-model="showAddCameraLabelModal"
title="Add group camera tag"
@cancel="
() => {
pendingLabel = '';
pendingDescription = '';
}
"
title="Add project camera label"
@cancel="reset"
@close="reset"
@esc="reset"
@ok="addPendingCameraLabel"
ok-title="Add tag"
ok-title="Add label"
ok-variant="secondary"
:ok-disabled="!pendingLabel.length"
cancel-variant="outline-secondary"
centered
>
<input type="text" v-model="pendingLabel" placeholder="label" />
<input type="text" v-model="pendingDescription" placeholder="description" />
<label for="camera-label" class="form-label">Label</label>
<b-form-input
id="camera-label"
v-model="pendingLabel"
placeholder="enter a new label"
class="mb-3"
/>
<label for="camera-description" class="form-label"
>Description (optional)</label
>
<b-form-input
id="camera-description"
v-model="pendingDescription"
placeholder="describe the label usage in your project"
/>
</b-modal>
<b-modal
v-model="showAddAudioLabelModal"
title="Add group audio tag"
@cancel="
() => {
pendingLabel = '';
pendingDescription = '';
}
"
title="Add project audio label"
@cancel="reset"
@close="reset"
@esc="reset"
@ok="addPendingAudioLabel"
ok-title="Add tag"
ok-title="Add label"
:ok-disabled="!pendingLabel.length"
ok-variant="secondary"
cancel-variant="outline-secondary"
centered
>
<input type="text" v-model="pendingLabel" placeholder="label" />
<input type="text" v-model="pendingDescription" placeholder="description" />
<label for="audio-label" class="form-label">Label</label>
<b-form-input
id="audio-label"
v-model="pendingLabel"
placeholder="enter a new label"
class="mb-3"
/>
<label for="audio-description" class="form-label"
>Description (optional)</label
>
<b-form-input
id="audio-description"
v-model="pendingDescription"
placeholder="describe the label usage in your project"
/>
</b-modal>
</template>
8 changes: 8 additions & 0 deletions browse-next/src/views/ManageProjectSettingsSubView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ const addIgnoredTag = async (tag: string, grouping: "camera" | "audio") => {
const reset = () => {
pendingIgnoredTag.value = [];
};
const pendingTagIsValid = computed<boolean>(() => {
return (
pendingIgnoredTag.value.length !== 0 &&
pendingIgnoredTag.value[0].trim().length !== 0
);
});
</script>
<template>
<h1 class="h5">Other project settings</h1>
Expand Down Expand Up @@ -224,6 +231,7 @@ const reset = () => {
@close="reset"
@esc="reset"
@ok="addPendingIgnoredTag"
:ok-disabled="!pendingTagIsValid"
ok-title="Add ignored tag"
ok-variant="secondary"
cancel-variant="outline-secondary"
Expand Down
8 changes: 8 additions & 0 deletions browse-next/src/views/ManageProjectTagSettingsSubView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ const reset = () => {
pendingTag.value = [];
};
const pendingTagIsValid = computed<boolean>(() => {
return (
pendingTag.value.length !== 0 && pendingTag.value[0].trim().length !== 0
);
});
// If there are no custom tags, display the defaultTags here in the default order.
// Add tag. delete tag, move tag up, move tag down, reset to defaults
</script>
Expand Down Expand Up @@ -330,6 +336,7 @@ const reset = () => {
@close="reset"
@esc="reset"
@ok="addPendingCameraTag"
:ok-disabled="!pendingTagIsValid"
ok-title="Add tag"
ok-variant="secondary"
cancel-variant="outline-secondary"
Expand All @@ -349,6 +356,7 @@ const reset = () => {
@close="reset"
@esc="reset"
@ok="addPendingAudioTag"
:ok-disabled="!pendingTagIsValid"
ok-title="Add tag"
ok-variant="secondary"
cancel-variant="outline-secondary"
Expand Down
11 changes: 7 additions & 4 deletions browse-next/src/views/ManageProjectView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ const navLinkClasses = ["nav-item", "nav-link", "border-0"];
<template>
<section-header>Manage project</section-header>
<div class="px-3 p-md-0">
<p>
<b-alert :model-value="true" variant="light" class="mb-3">
Add or remove users who have access to this project, change the default
tags and labels that users of this project see when tagging recordings.
<br />Customise which tags you'd like your users to see on your project
dashboard.
</p>
</b-alert>
<!-- <p>-->
<!-- If I'm the only user, and there are no devices, and no recordings, then we-->
<!-- should show the setup screen-->
Expand Down Expand Up @@ -47,7 +47,8 @@ const navLinkClasses = ["nav-item", "nav-link", "border-0"];
:to="{
name: 'project-tagging-settings',
}"
>Tagging</router-link
>Tag<span class="d-none d-sm-inline-block">ging</span
><span class="d-sm-none">s</span></router-link
>
<router-link
:class="[
Expand All @@ -69,7 +70,9 @@ const navLinkClasses = ["nav-item", "nav-link", "border-0"];
:to="{
name: 'project-misc-settings',
}"
>Other settings</router-link
><span
>Other<span class="d-none d-sm-inline-block">&nbsp;settings</span></span
></router-link
>
<!-- <router-link-->
<!-- :class="[-->
Expand Down

0 comments on commit 750f431

Please sign in to comment.