hotfix (dashboard): display allow email contact in card box client
- Added the `allowEmailContact` property to the `CardBoxClient` component to display the email contact status. - Added the `allowEmailContact` computed property to the `Person` model to determine if email contact is allowed based on the related datasets. - Preloaded the datasets relation in the `AuthorsController` to access the pivot attributes. - Updated the `Dashboard.vue` to pass the `allowEmailContact` prop to the `CardBoxClient` component. - Updated the `array_contains_types` validation rule to correct the error message for descriptions. - Updated the `FormCheckRadio.vue` to correctly handle the radio button and checkbox components.
This commit is contained in:
parent
09f65359f9
commit
f89b119b18
6 changed files with 31 additions and 49 deletions
|
@ -9,6 +9,7 @@ export default class AuthorsController {
|
||||||
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
|
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
|
||||||
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
|
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
|
||||||
const authors = await Person.query()
|
const authors = await Person.query()
|
||||||
|
.preload('datasets')
|
||||||
.where('name_type', 'Personal')
|
.where('name_type', 'Personal')
|
||||||
.whereHas('datasets', (dQuery) => {
|
.whereHas('datasets', (dQuery) => {
|
||||||
dQuery.wherePivot('role', 'author');
|
dQuery.wherePivot('role', 'author');
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { DateTime } from 'luxon';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import Dataset from './dataset.js';
|
import Dataset from './dataset.js';
|
||||||
import BaseModel from './base_model.js';
|
import BaseModel from './base_model.js';
|
||||||
import type { ManyToMany } from "@adonisjs/lucid/types/relations";
|
import type { ManyToMany } from '@adonisjs/lucid/types/relations';
|
||||||
|
|
||||||
export default class Person extends BaseModel {
|
export default class Person extends BaseModel {
|
||||||
public static namingStrategy = new SnakeCaseNamingStrategy();
|
public static namingStrategy = new SnakeCaseNamingStrategy();
|
||||||
|
@ -64,9 +64,8 @@ export default class Person extends BaseModel {
|
||||||
// return '2023-03-21 08:45:00';
|
// return '2023-03-21 08:45:00';
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
@computed({
|
@computed({
|
||||||
serializeAs: 'dataset_count',
|
serializeAs: 'dataset_count',
|
||||||
})
|
})
|
||||||
public get datasetCount() {
|
public get datasetCount() {
|
||||||
const stock = this.$extras.datasets_count; //my pivot column name was "stock"
|
const stock = this.$extras.datasets_count; //my pivot column name was "stock"
|
||||||
|
@ -79,6 +78,16 @@ export default class Person extends BaseModel {
|
||||||
return contributor_type;
|
return contributor_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed({ serializeAs: 'allow_email_contact' })
|
||||||
|
public get allowEmailContact() {
|
||||||
|
// If the datasets relation is missing or empty, return false instead of null.
|
||||||
|
if (!this.datasets || this.datasets.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Otherwise return the pivot attribute from the first related dataset.
|
||||||
|
return this.datasets[0].$extras?.pivot_allow_email_contact;
|
||||||
|
}
|
||||||
|
|
||||||
@manyToMany(() => Dataset, {
|
@manyToMany(() => Dataset, {
|
||||||
pivotForeignKey: 'person_id',
|
pivotForeignKey: 'person_id',
|
||||||
pivotRelatedForeignKey: 'document_id',
|
pivotRelatedForeignKey: 'document_id',
|
||||||
|
|
|
@ -39,6 +39,10 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
allowEmailContact: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const pillType = computed(() => {
|
const pillType = computed(() => {
|
||||||
|
@ -81,9 +85,8 @@ const pillType = computed(() => {
|
||||||
<h4 class="text-xl text-ellipsis">
|
<h4 class="text-xl text-ellipsis">
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</h4>
|
</h4>
|
||||||
<p class="text-gray-500 dark:text-slate-400">
|
<p class="text-gray-500 dark:text-slate-400">
|
||||||
<!-- {{ date }} @ {{ login }} -->
|
<div v-if="props.allowEmailContact"> {{ email }}</div>
|
||||||
{{ email }}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</BaseLevel>
|
</BaseLevel>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name: string;
|
name: string;
|
||||||
type?: 'checkbox' | 'radio' | 'switch';
|
type?: 'checkbox' | 'radio' | 'switch';
|
||||||
|
@ -10,58 +9,27 @@ interface Props {
|
||||||
inputValue: string | number | boolean;
|
inputValue: string | number | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<Props>();
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: 'checkbox',
|
|
||||||
validator: (value: string) => ['checkbox', 'radio', 'switch'].includes(value),
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
modelValue: {
|
|
||||||
type: [Array, String, Number, Boolean],
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
inputValue: {
|
|
||||||
type: [String, Number, Boolean],
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});// const props = defineProps<Props>();
|
|
||||||
|
|
||||||
// const emit = defineEmits(['update:modelValue']);
|
|
||||||
const emit = defineEmits<{ (e: 'update:modelValue', value: Props['modelValue']): void }>();
|
const emit = defineEmits<{ (e: 'update:modelValue', value: Props['modelValue']): void }>();
|
||||||
|
|
||||||
const computedValue = computed({
|
const computedValue = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
// If type is radio, wrap the new value inside an array.
|
emit('update:modelValue', props.type === 'radio' ? [value] : value);
|
||||||
if (props.type === 'radio') {
|
|
||||||
emit('update:modelValue', [value]);
|
|
||||||
} else {
|
|
||||||
emit('update:modelValue', value);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const inputType = computed(() => (props.type === 'radio' ? 'radio' : 'checkbox'));
|
const inputType = computed(() => (props.type === 'radio' ? 'radio' : 'checkbox'));
|
||||||
|
|
||||||
// Define isChecked for radio inputs: it's true when the current modelValue equals the inputValue
|
// Define isChecked for radio inputs: it's true when the current modelValue equals the inputValue
|
||||||
const isChecked = computed(() => {
|
const isChecked = computed(() => {
|
||||||
if (props.type === 'radio') {
|
if (Array.isArray(computedValue.value) && computedValue.value.length > 0) {
|
||||||
return Array.isArray(computedValue.value) &&
|
return props.type === 'radio'
|
||||||
computedValue.value.length > 0 &&
|
? computedValue.value[0] === props.inputValue
|
||||||
computedValue.value[0] === props.inputValue;
|
: computedValue.value.includes(props.inputValue);
|
||||||
} else if (props.type === 'checkbox') {
|
}
|
||||||
return Array.isArray(computedValue.value) &&
|
return computedValue.value === props.inputValue;
|
||||||
computedValue.value.length > 0 &&
|
|
||||||
computedValue.value.includes(props.inputValue);
|
|
||||||
}
|
|
||||||
return computedValue.value === props.inputValue;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ const userHasRoles = (roleNames: Array<string>): boolean => {
|
||||||
:date="client.created_at"
|
:date="client.created_at"
|
||||||
:text="client.identifier_orcid"
|
:text="client.identifier_orcid"
|
||||||
:count="client.dataset_count"
|
:count="client.dataset_count"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col justify-between">
|
<div class="flex flex-col justify-between">
|
||||||
|
|
|
@ -53,9 +53,9 @@ async function arrayContainsTypes(value: unknown, options: Options, field: Field
|
||||||
} else if (field.getFieldPath() === 'descriptions') {
|
} else if (field.getFieldPath() === 'descriptions') {
|
||||||
// For descriptions we expect one abstracts description and minimum one translated description.
|
// For descriptions we expect one abstracts description and minimum one translated description.
|
||||||
if (!hasTypeA && !hasTypeB) {
|
if (!hasTypeA && !hasTypeB) {
|
||||||
errorMessage = 'For descriptions, define one abstracts description and minimum one translated description.';
|
errorMessage = 'For descriptions, define one abstract description and minimum one translated description.';
|
||||||
} else if (!hasTypeA) {
|
} else if (!hasTypeA) {
|
||||||
errorMessage = 'For descriptions, define one abstracts description.';
|
errorMessage = 'For descriptions, define one abstract description.';
|
||||||
} else if (!hasTypeB) {
|
} else if (!hasTypeB) {
|
||||||
errorMessage = 'For descriptions, define minimum one translated description.';
|
errorMessage = 'For descriptions, define minimum one translated description.';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue