Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Checkbox/Checkbox.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<label
class="flex select-none items-center text-base-normal"
class="text-base flex select-none items-center"
:class="{'w-5': !label}"
>
<input
Expand Down
6 changes: 6 additions & 0 deletions src/components/Form/FormGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ export default {
validator: (val) => ['default', 'fullWidth'].includes(val),
},
},
emits: [
/** Emitted when a field prop changes. Payload: `(fieldName, propName, newValue, [localeKey])`. The `localeKey` will be null for fields that are not multilingual. This event is fired every time the `value` changes, so you should [debounce](https://www.npmjs.com/package/debounce) event callbacks that contain resource-intensive code. */
'change',
'set-errors',
],

computed: {
/**
* All fields assigned to this group
Expand Down
7 changes: 6 additions & 1 deletion src/components/Form/FormPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ export default {
},
spacingVariant: String,
},
emits: [
/** Emitted when a field prop changes. Payload: `(fieldName, propName, newValue, [localeKey])`. The `localeKey` will be null for fields that are not multilingual. This event is fired every time the `value` changes, so you should [debounce](https://www.npmjs.com/package/debounce) event callbacks that contain resource-intensive code. */
'change',
'set-errors',
],
data() {
return {
hasRecentSave: false,
Expand Down Expand Up @@ -152,7 +157,7 @@ export default {

footerSpacingStyle() {
if (this.spacingVariant === 'fullWidth') {
return '!px-0 !py-12';
return '!px-0';
}
return '';
},
Expand Down
12 changes: 8 additions & 4 deletions src/components/Form/fields/FieldAuthors.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,44 @@
<FieldText
:name="'givenName'"
:value="row.givenName"
:all-errors="{givenName: errors?.[index]?.givenName}"
@change="
(fieldName, _, fieldValue) => {
updateRow(index, fieldName, fieldValue);
}
"
:all-errors="{givenName: errors?.[index]?.givenName}"
/>
</TableCell>
<TableCell>
<FieldText
:name="'familyName'"
:value="row.familyName"
:all-errors="{familyName: errors?.[index]?.familyName}"
@change="
(fieldName, _, fieldValue) => {
updateRow(index, fieldName, fieldValue);
}
"
:all-errors="{familyName: errors?.[index]?.familyName}"
/>
</TableCell>
<TableCell>
<FieldText
:name="'orcid'"
:value="row.orcid"
:all-errors="{orcid: errors?.[index]?.orcid}"
@change="
(fieldName, _, fieldValue) => {
updateRow(index, fieldName, fieldValue);
}
"
:all-errors="{orcid: errors?.[index]?.orcid}"
/>
</TableCell>
<TableCell>
<PkpButton :is-link="true" @click="deleteRow(index)">
<PkpButton
:is-link="true"
:is-warnable="true"
@click="deleteRow(index)"
>
{{ t('common.delete', []) }}
</PkpButton>
</TableCell>
Expand Down
8 changes: 7 additions & 1 deletion src/components/Form/fields/FieldTextarea.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ export default {
type: String,
default: 'normal',
validator: function (value) {
return ['small', 'normal', 'large'].indexOf(value) !== -1;
return (
['small', 'small-height', 'normal', 'large'].indexOf(value) !== -1
);
},
},
},
Expand Down Expand Up @@ -118,6 +120,10 @@ export default {
height: 8em;
}

.pkpFormField--small-height .pkpFormField--textarea__input {
height: 10em;
}

.pkpFormField--large .pkpFormField--textarea__input {
height: 40em;
}
Expand Down
33 changes: 32 additions & 1 deletion src/composables/useForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,15 @@ export function useForm(_form = {}, {customSubmit} = {}) {

function initEmptyForm(
formId,
{action, method, locales, showErrorFooter, spacingVariant} = {},
{
action,
method,
locales,
showErrorFooter,
spacingVariant,
onSuccess,
onSet,
} = {},
) {
if (!form.value) {
form.value = {};
Expand All @@ -379,6 +387,9 @@ export function useForm(_form = {}, {customSubmit} = {}) {
form.value.locales = locales;
form.value.showErrorFooter = showErrorFooter;
form.value.spacingVariant = spacingVariant || 'default';
form.value.onSuccess = onSuccess || undefined;
form.value.onSet = onSet || set;

setMethod(method || 'POST');
setAction(action || 'emit');
setLocales(locales);
Expand Down Expand Up @@ -592,6 +603,25 @@ export function useForm(_form = {}, {customSubmit} = {}) {
);
}

/**
* Adds or updates a textarea field in the form.
*
* @param {string} fieldName - The name (or key) of the field.
* @param {Object} fieldOptions - Configuration options for the field.
* @param {Object} [opts] - Optional settings.
* @param {boolean} [opts.override] - If true and the field already exists, it will be fully overridden.
*/
function addFieldHtml(fieldName, {...commonFields} = {}, opts) {
return addField(
fieldName,
{
component: 'field-html',
...commonFields,
},
opts,
);
}

/**
* Adds or updates a FieldCheckbox in the form.
* @param {string} fieldName - The name of the field
Expand Down Expand Up @@ -670,6 +700,7 @@ export function useForm(_form = {}, {customSubmit} = {}) {
addFieldTextArea,
addFieldCheckbox,
addFieldComponent,
addFieldHtml,
getField,
};
}
33 changes: 33 additions & 0 deletions src/managers/CitationManager/CitationManager.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Primary,
Controls,
Stories,
Meta,
ArgTypes,
} from '@storybook/addon-docs/blocks';
import * as CitationManager from './CitationManager.stories.js';

<Meta of={CitationManager} />

# Citation manager

Listing of Citations.

## Props

<ArgTypes />

## Extension points for plugins

For more details and examples on how to use them, check out [Plugins guide](..?path=/docs/guide-plugins--docs)

The name of the Pinia store is `CitationManager`.

- `getTopItems`: Add/Change items in the top right, where the `Upload / Select` button is.
- `getItemActions`: Add/Change the list of actions that are displayed after clicking the 3 dots button.
- `getColumns`: Add/Change the columns being displayed in the table.
- ...

<Primary />
<Controls />
<Stories />
17 changes: 17 additions & 0 deletions src/managers/CitationManager/CitationManager.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import CitationManager from './CitationManager.vue';

export default {
title: 'Managers/CitationManager',
component: CitationManager,
render: (args) => ({
components: {CitationManager},
setup() {
return {args};
},
template: `<CitationManager v-bind="args"/>`,
}),
};

export const Base = {
args: {},
};
108 changes: 108 additions & 0 deletions src/managers/CitationManager/CitationManager.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<div>
<CitationManagerMetadataLookup />
<div class="pt-3">
<CitationManagerAddRawCitations />
</div>
<CitationManagerStatusProcessed
v-if="citationStore.citationsMetadataLookup"
/>
<div>
<PkpButton
:is-disabled="!citationStore.canEditPublication"
:is-link="true"
@click="citationStore.citationDeleteAllCitations"
>
{{ t('submission.citations.structured.deleteAllLink') }}
</PkpButton>
</div>
<PkpTable :aria-label="t('submission.citations.structured')">
<template #label>
<h3 class="text-4 font-semibold">
{{ t('submission.citations.structured') }}
</h3>
<span class="text-lg-normal">
{{ t('submission.citations.structured.descriptionTable') }}
</span>
</template>
<template #top-controls>
<div class="flex gap-x-2">
<component
:is="Components[action.component] || action.component"
v-bind="action.props || {}"
v-for="(action, i) in citationStore.topItems"
:key="i"
></component>
</div>
</template>
<TableHeader>
<TableColumn
v-for="(column, i) in citationStore.columns"
:key="i"
:class="i > 0 ? '!w-16 !text-center' : ''"
>
<span v-if="column.isHeaderComponent">
<component :is="Components[column.header] || column.header" />
</span>
<span v-else :class="column.headerSrOnly ? 'sr-only' : ''">
{{ column.header }}
</span>
</TableColumn>
</TableHeader>
<TableBody
:empty-text="t('submission.citations.structured.emptyCitations')"
>
<TableRow
v-for="citation in citationStore.citationsFiltered"
:key="citation.id"
>
<component
:is="Components[column.component] || column.component"
v-for="(column, index) in citationStore.columns"
:key="index"
v-bind="citation"
:citation="citation"
></component>
</TableRow>
</TableBody>
</PkpTable>
</div>
</template>

<script setup>
import {useLocalize} from '@/composables/useLocalize';
import PkpButton from '@/components/Button/Button.vue';
import PkpTable from '@/components/Table/Table.vue';
import TableColumn from '@/components/Table/TableColumn.vue';
import TableHeader from '@/components/Table/TableHeader.vue';
import TableBody from '@/components/Table/TableBody.vue';
import TableRow from '@/components/Table/TableRow.vue';
import CitationManagerCellCitation from '@/managers/CitationManager/CitationManagerCellCitation.vue';
import CitationManagerCellToggle from '@/managers/CitationManager/CitationManagerCellToggle.vue';
import CitationManagerToggleAll from '@/managers/CitationManager/CitationManagerToggleAll.vue';
import CitationManagerCellActions from '@/managers/CitationManager/CitationManagerCellActions.vue';
import CitationManagerSearchField from '@/managers/CitationManager/CitationManagerSearchField.vue';
import CitationManagerStatusProcessed from '@/managers/CitationManager/CitationManagerStatusProcessed.vue';
import CitationManagerAddRawCitations from '@/managers/CitationManager/CitationManagerAddRawCitations.vue';
import CitationManagerMetadataLookup from '@/managers/CitationManager/CitationManagerMetadataLookup.vue';
import {useCitationManagerStore} from './citationManagerStore.js';

const {t} = useLocalize();

const Components = {
CitationManagerCellCitation,
CitationManagerCellToggle,
CitationManagerToggleAll,
CitationManagerCellActions,
CitationManagerSearchField,
};

const props = defineProps({
submission: {type: Object, required: true},
publication: {type: Object, required: true},
canEdit: {type: Boolean, required: true},
componentForms: {type: Object, required: true},
});

const citationStore = useCitationManagerStore(props);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<PkpForm v-bind="citationStore.formAddRawCitations"></PkpForm>
</template>

<script setup>
import {useCitationManagerStore} from './citationManagerStore.js';

const citationStore = useCitationManagerStore();
</script>
33 changes: 33 additions & 0 deletions src/managers/CitationManager/CitationManagerCellActions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<TableCell>
<DropdownActions
v-show="citationStore.canEditPublication"
button-variant="ellipsis"
:label="t('common.moreActions')"
:actions="citationStore.getItemActions({citation})"
@action="(actionName) => handleAction(actionName, citation)"
/>
</TableCell>
</template>

<script setup>
import {computed} from 'vue';
import {useLocalize} from '@/composables/useLocalize';
import TableCell from '@/components/Table/TableCell.vue';
import DropdownActions from '@/components/DropdownActions/DropdownActions.vue';
import {useCitationManagerStore} from './citationManagerStore';

const {t} = useLocalize();

const props = defineProps({
citation: {type: Object, required: true},
});

const citation = computed(() => props.citation);

const citationStore = useCitationManagerStore();

function handleAction(actionName, citation) {
citationStore[actionName]({citation});
}
</script>
Loading
Loading