Skip to content

Commit

Permalink
Feature #824: Redesign top section of Entities and Submissions pages
Browse files Browse the repository at this point in the history
  • Loading branch information
sadiqkhoja committed Feb 6, 2025
1 parent 6e26342 commit 0e82126
Show file tree
Hide file tree
Showing 31 changed files with 330 additions and 221 deletions.
37 changes: 37 additions & 0 deletions src/assets/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,17 @@ a {
> .btn-default + .btn-default { border-left: 1px solid #ccc; }
}

.btn-outlined {
background-color: #fff;
color: $color-action-background;
border: 1px solid $color-action-background;

&:hover, &:focus, &:active:focus {
color: #fff;
background-color: $color-action-background;
&[aria-disabled="true"], &.disabled, fieldset[disabled] & { background-color: #ddd; }
}
}

////////////////////////////////////////////////////////////////////////////////
// DROPDOWN MENUS
Expand Down Expand Up @@ -535,6 +545,7 @@ select {
.icon-filter {
color: #999;
margin-right: $margin-right-icon;
font-size: 20px;
}
}

Expand Down Expand Up @@ -927,4 +938,30 @@ becomes more complicated.

.odk-form :not(svg|*) {
all: revert;
}

////////////////////////////////////////////////////////////////////////////////
// The action bar shown above the data table

.table-actions-bar {
background-color: $color-subpanel-background;
padding: 10px 20px;

.form-inline {
margin-bottom: 0;
padding-bottom: 0;
}

.form-label {
height: auto;
cursor: pointer;
}

.form-group .form-control {
border-bottom: none;
}

.form-group + .form-group {
margin-left: 30px;
}
}
4 changes: 2 additions & 2 deletions src/components/audit/filters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ except according to the terms contained in the LICENSE file.
<template>
<form class="form-inline" @submit.prevent>
<div class="form-group">
<span class="icon-filter"></span><span>{{ $t('common.filter') }}</span>
<span class="icon-filter"></span>
</div>
<audit-filters-action :model-value="action"
@update:model-value="$emit('update:action', $event)"/>
<date-range-picker :model-value="dateRange"
:placeholder="$t('field.dateRange')" required
:label="$t('field.dateRange')" required
@update:model-value="$emit('update:dateRange', $event)"/>
</form>
</template>
Expand Down
4 changes: 2 additions & 2 deletions src/components/audit/filters/action.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<label id="audit-filters-action" class="form-group">
<select class="form-control" :value="modelValue"
<label id="audit-filters-action" for="audit-actions" class="form-group">
<select id="audit-actions" ref="auditActions" class="form-control" :value="modelValue"
@change="$emit('update:modelValue', $event.target.value)">
<option v-for="option of options" :key="option.value"
:class="option.htmlClass" :value="option.value">
Expand Down
4 changes: 3 additions & 1 deletion src/components/audit/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ except according to the terms contained in the LICENSE file.
<template>
<div>
<p class="page-body-heading">{{ $t('heading[0]') }}</p>
<audit-filters v-model:action="action" v-model:dateRange="dateRange"/>
<div class="table-actions-bar">
<audit-filters v-model:action="action" v-model:dateRange="dateRange"/>
</div>
<audit-table/>
<loading :state="audits.initiallyLoading"/>
<p v-show="audits.dataExists && audits.length === 0"
Expand Down
55 changes: 37 additions & 18 deletions src/components/dataset/entities.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,27 @@ except according to the terms contained in the LICENSE file.
<div id="dataset-entities">
<page-section>
<template #heading>
<span>{{ $t('resource.entities') }}</span>
<button v-if="project.dataExists && project.permits('entity.create')"
id="dataset-entities-upload-button" type="button"
class="btn btn-primary" @click="upload.show()">
<span class="icon-upload"></span>{{ $t('action.upload') }}
</button>
<template v-if="deletedEntityCount.dataExists">
<button v-if="canDelete && (deletedEntityCount.value > 0 || deleted)" type="button"
class="btn toggle-deleted-entities" :class="{ 'btn-danger': deleted, 'btn-link': !deleted }"
@click="toggleDeleted">
<span class="icon-trash"></span>{{ $tcn('action.toggleDeletedEntities', deletedEntityCount.value) }}
<span v-show="deleted" class="icon-close"></span>
<div class="dataset-entities-heading-row">
<button v-if="project.dataExists && project.permits('entity.create')"
id="dataset-entities-upload-button" type="button"
class="btn btn-primary" @click="upload.show()">
<span class="icon-upload"></span>{{ $t('upload') }}
</button>
</template>
<odata-data-access :analyze-disabled="deleted"
:analyze-disabled-message="$t('analyzeDisabledDeletedData')"
@analyze="analyze.show()"/>
<template v-if="deletedEntityCount.dataExists">
<button v-if="canDelete && (deletedEntityCount.value > 0 || deleted)" type="button"
class="btn toggle-deleted-entities" :class="{ 'btn-danger': deleted, 'btn-link': !deleted }"
@click="toggleDeleted">
<span class="icon-trash"></span>{{ $tcn('action.toggleDeletedEntities', deletedEntityCount.value) }}
<span v-show="deleted" class="icon-close"></span>
</button>
</template>
<odata-data-access :analyze-disabled="deleted"
:analyze-disabled-message="$t('analyzeDisabledDeletedData')"
@analyze="analyze.show()"/>
<entity-download-button
:aria-disabled="deleted"
v-tooltip.aria-describedby="deleted ? $t('downloadDisabled') : null"/>
</div>
</template>
<template #body>
<entity-list ref="list" :project-id="projectId"
Expand All @@ -54,6 +58,7 @@ import OdataDataAccess from '../odata/data-access.vue';
import PageSection from '../page/section.vue';
import useEntities from '../../request-data/entities';
import useQueryRef from '../../composables/query-ref';
import EntityDownloadButton from '../entity/download-button.vue';

import { apiPaths } from '../../util/request';
import { loadAsync } from '../../util/load-async';
Expand All @@ -68,9 +73,13 @@ export default {
OdataDataAccess,
EntityList,
EntityUpload: defineAsyncComponent(loadAsync('EntityUpload')),
EntityDownloadButton,
PageSection
},
inject: ['alert'],
provide() {
return { projectId: this.projectId, datasetName: this.datasetName };
},
props: {
projectId: {
type: String,
Expand Down Expand Up @@ -155,8 +164,6 @@ export default {
<style lang="scss">
@import '../../assets/scss/variables';

#odata-data-access { float: right; }

#dataset-entities {
.toggle-deleted-entities {
margin-left: 8px;
Expand All @@ -175,12 +182,24 @@ export default {
left: 12px;
font-size: 14px;
}

.dataset-entities-heading-row {
display: flex;
align-items: center;
gap: 10px;
}

#odata-data-access {
margin-left: auto;
font-size: initial;
}
}
</style>

<i18n lang="json5">
{
"en": {
"upload": "Upload Entities",
"alert": {
"upload": "Success! Your Entities have been uploaded."
},
Expand Down
44 changes: 34 additions & 10 deletions src/components/date-range-picker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<label class="form-group"><!-- eslint-disable-line vuejs-accessibility/label-has-for -->
<label id="date-range-picker-container" for="datepicker" class="form-group">
<!-- We use a class to indicate whether the input is required, because
flatpickr does not support the `required` attribute:
https://github.com/ankurk91/vue-flatpickr-component/issues/47 -->
<flatpickr ref="flatpickr" v-model="flatpickrValue" :config="config"
class="form-control" :class="{ required }"
<flatpickr id="datepicker" ref="flatpickr" v-model="flatpickrValue" :config="config"
class="form-control"
:class="{ required, 'flatpickr-input': true, 'has-value': modelValue.length === 2, none: modelValue.length === 0 }"
:aria-disabled="disabled" v-tooltip.aria-describedby="disabledMessage"
:placeholder="requiredLabel(placeholder, required)" autocomplete="off"
:placeholder="$t('common.none')" autocomplete="off"
@keydown="stopPropagationIfDisabled"
@on-close="close"/>
<template v-if="!required">
Expand All @@ -26,7 +27,9 @@ except according to the terms contained in the LICENSE file.
<span aria-hidden="true">&times;</span>
</button>
</template>
<span class="form-label">{{ requiredLabel(placeholder, required) }}</span>
<span v-show="!disabled && (required || modelValue.length < 2)" aria-hidden="true" class="icon-angle-down">
</span>
<span class="form-label">{{ requiredLabel(label, required) }}</span>
</label>
</template>

Expand Down Expand Up @@ -70,7 +73,7 @@ export default {
type: Boolean,
default: false
},
placeholder: {
label: {
type: String,
required: true
},
Expand Down Expand Up @@ -187,13 +190,34 @@ export default {
}

.form-inline .flatpickr-input {
// Leave space for the .close button.
width: 205px;
&.required { width: 193px };
width: 87px;

&:lang(ja) {
&.has-value {
// Leave space for the .close button.
width: 207px;
&.required { width: 193px };
}

&.has-value:lang(ja) {
width: 252px;
&.required { width: 240px; }
}

&.none {
font-style: italic;
}
}

#date-range-picker-container {
.icon-angle-down {
font-size: 16px;
color: #555555;
font-weight: bold;
vertical-align: -4px;
}

.form-label {
transform: translateY(2px);
}
}
</style>
17 changes: 2 additions & 15 deletions src/components/entity/download-button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@ except according to the terms contained in the LICENSE file.
-->
<template>
<a id="entity-download-button" class="btn btn-primary" :href="href">
<span class="icon-arrow-circle-down"></span>{{ text }}
<span class="icon-arrow-circle-down"></span>
<span>{{ $t('action.download') }}</span>
</a>
</template>

<script setup>
import { computed, inject } from 'vue';
import { useI18n } from 'vue-i18n';

import { apiPaths } from '../../util/request';
import { useI18nUtils } from '../../util/i18n';
import { useRequestData } from '../../request-data';

const props = defineProps({
odataFilter: String
Expand All @@ -33,16 +30,6 @@ const datasetName = inject('datasetName');
const href = computed(() =>
apiPaths.entities(projectId, datasetName, '.csv', { $filter: props.odataFilter }));

const { dataset, odataEntities } = useRequestData();
const { t } = useI18n();
const { tn } = useI18nUtils();
const text = computed(() => (props.odataFilter == null
? (dataset.dataExists
? tn('action.download.unfiltered', dataset.entities)
: '') // The button is not visible in this case.
: (odataEntities.dataExists
? tn('action.download.filtered.withCount', odataEntities.count)
: t('action.download.filtered.withoutCount'))));
</script>

<i18n lang="json5">
Expand Down
2 changes: 1 addition & 1 deletion src/components/entity/filters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ except according to the terms contained in the LICENSE file.
<template>
<span id="entity-filters">
<div class="form-group">
<span class="icon-filter"></span><span>{{ $t('common.filter') }}</span>
<span class="icon-filter"></span>
</div>
<entity-filters-conflict :model-value="conflict" :disabled="disabled"
:disabled-message="disabledMessage" @update:model-value="$emit('update:conflict', $event)"/>
Expand Down
12 changes: 11 additions & 1 deletion src/components/entity/filters/conflict.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,19 @@ defineEmits(['update:modelValue']);
const { t } = useI18n();
const options = computed(() => [true, false].map(value =>
({ value, text: t(`conflict.${value}`) })));
const placeholder = (counts) => t('placeholder', counts);
const placeholder = (counts) => {
if (counts.total === counts.selected) return t('common.none');

return t('placeholder', counts);
};
</script>

<style lang="scss">
#entity-filters-conflict .none {
font-style: italic;
}
</style>

<i18n lang="json5">
{
"en": {
Expand Down
Loading

0 comments on commit 0e82126

Please sign in to comment.