Skip to content

Commit

Permalink
[TGA-67] New form for AuthorSignOff (#17)
Browse files Browse the repository at this point in the history
* [TGA-67] New form for AuthorSignOff
Added ability to view completed form from Superdesk

* Email a copy of the form to the signee
  • Loading branch information
MarkLark86 authored Nov 26, 2023
1 parent f02996d commit 64acbef
Show file tree
Hide file tree
Showing 15 changed files with 1,151 additions and 208 deletions.
46 changes: 25 additions & 21 deletions client/extensions/tga-sign-off/src/components/SignOffListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,12 @@ interface IPropsBase {
user: IUser;
readOnly?: boolean;
appendContentDivider?: boolean;
buttonProps?: {
text: string;
icon: string;
onClick(): void;
};
buttonProps?: Array<React.ComponentProps<typeof Button>>;
}

interface IPropsApproved extends IPropsBase {
state: 'approved';
fundingSource: string;
affiliation: string;
email: string;
date: string;
}

Expand Down Expand Up @@ -59,25 +54,34 @@ export function SignOffListItem(props: IProps) {
)}

{props.buttonProps == null ? null : (
<ButtonGroup align="end">
<Button
type="default"
text={props.buttonProps.text}
icon={props.buttonProps.icon}
onClick={props.buttonProps.onClick}
/>
</ButtonGroup>
<React.Fragment>
{props.buttonProps.length === 1 ? (
<ButtonGroup align="end">
<Button
key={props.buttonProps[0].text}
{...props.buttonProps[0]}
/>
</ButtonGroup>
) : (
<div className="sd-margin-l--auto">
<ButtonGroup orientation="vertical">
{props.buttonProps.map((buttonProps) => (
<Button
key={buttonProps.text}
{...buttonProps}
/>
))}
</ButtonGroup>
</div>
)}
</React.Fragment>
)}
</div>
{props.state !== 'approved' ? null : (
<React.Fragment>
<div className="sd-display-flex-column sd-margin-l--5 sd-padding-l--0-5 sd-margin-t--1">
<label className="form-label form-label--block">{gettext('Funding Source:')}</label>
<span>{props.fundingSource.trim()}</span>
</div>
<div className="sd-display-flex-column sd-margin-l--5 sd-padding-l--0-5 sd-margin-t--1">
<label className="form-label form-label--block">{gettext('Affiliation:')}</label>
<span>{props.affiliation.trim()}</span>
<label className="form-label form-label--block">{gettext('Email:')}</label>
<span>{props.email.trim()}</span>
</div>
</React.Fragment>
)}
Expand Down
58 changes: 41 additions & 17 deletions client/extensions/tga-sign-off/src/components/fields/editor.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import * as React from 'react';

import {IUser} from 'superdesk-api';
import {IEditorProps, IUserSignOff, IPublishSignOff} from '../../interfaces';
import {IEditorProps, IAuthorSignOffData, IPublishSignOff} from '../../interfaces';
import {superdesk} from '../../superdesk';

import {hasUserSignedOff, getListAuthorIds, loadUsersFromPublishSignOff, getSignOffDetails} from '../../utils';
import {
hasUserSignedOff,
getListAuthorIds,
loadUsersFromPublishSignOff,
getSignOffDetails,
viewSignOffApprovalForm,
} from '../../utils';

import {Button, ToggleBox} from 'superdesk-ui-framework/react';
import {SignOffListItem} from '../SignOffListItem';
Expand Down Expand Up @@ -83,7 +89,7 @@ export class UserSignOffField extends React.Component<IEditorProps, IState> {
});
}

removeSignOff(sign_off_data: IUserSignOff) {
removeSignOff(signOffData: IAuthorSignOffData) {
const {confirm, notify} = superdesk.ui;
const {gettext} = superdesk.localization;
const publishSignOff: IPublishSignOff | undefined = this.props.item.extra?.publish_sign_off;
Expand All @@ -100,7 +106,7 @@ export class UserSignOffField extends React.Component<IEditorProps, IState> {
if (response) {
superdesk.httpRequestVoidLocal({
method: 'DELETE',
path: `/sign_off_request/${this.props.item._id}/${sign_off_data.user_id}`,
path: `/sign_off_request/${this.props.item._id}/${signOffData.user_id}`,
}).then(() => {
notify.success(gettext('Publishing sign off removed'));
}).catch((error: string) => {
Expand Down Expand Up @@ -148,21 +154,39 @@ export class UserSignOffField extends React.Component<IEditorProps, IState> {
{count: publishSignOff.sign_offs.length}
)}
>
{publishSignOff.sign_offs.map((sign_off_data, index) => (
this.state.users[sign_off_data.user_id] == null ? null : (
{publishSignOff.sign_offs.map((signOffData, index) => (
this.state.users[signOffData.user_id] == null ? null : (
<SignOffListItem
state="approved"
user={this.state.users[sign_off_data.user_id]}
user={this.state.users[signOffData.user_id]}
readOnly={this.props.readOnly}
appendContentDivider={index < publishSignOff.sign_offs.length - 1}
buttonProps={this.props.readOnly ? undefined : {
buttonProps={this.props.readOnly ? [{
type: 'success',
text: gettext('View Form'),
icon: 'external',
onClick: viewSignOffApprovalForm.bind(
undefined,
this.props.item._id,
signOffData.user_id
),
}] : [{
type: 'success',
text: gettext('View Form'),
icon: 'external',
onClick: viewSignOffApprovalForm.bind(
undefined,
this.props.item._id,
signOffData.user_id
),
}, {
type: 'default',
text: gettext('Remove'),
icon: 'trash',
onClick: this.removeSignOff.bind(this, sign_off_data)
}}
fundingSource={sign_off_data.funding_source}
affiliation={sign_off_data.affiliation}
date={sign_off_data.sign_date}
onClick: this.removeSignOff.bind(this, signOffData)
}]}
email={signOffData.author.email}
date={signOffData.sign_date}
/>
)
))}
Expand All @@ -183,11 +207,11 @@ export class UserSignOffField extends React.Component<IEditorProps, IState> {
user={this.state.users[pendingReview.user_id]}
readOnly={this.props.readOnly}
appendContentDivider={true}
buttonProps={this.props.readOnly ? undefined : {
buttonProps={this.props.readOnly ? undefined : [{
text: gettext('Resend'),
icon: 'refresh',
onClick: this.sendSignOff.bind(this, [pendingReview.user_id]),
}}
}]}
date={pendingReview.expires}
/>
)
Expand All @@ -200,11 +224,11 @@ export class UserSignOffField extends React.Component<IEditorProps, IState> {
user={this.state.users[authorId]}
readOnly={this.props.readOnly}
appendContentDivider={true}
buttonProps={this.props.readOnly ? undefined : {
buttonProps={this.props.readOnly ? undefined : [{
text: gettext('Send'),
icon: 'assign',
onClick: this.sendSignOff.bind(this, [authorId]),
}}
}]}
/>
)
))}
Expand Down
19 changes: 14 additions & 5 deletions client/extensions/tga-sign-off/src/components/fields/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import * as React from 'react';

import {IPreviewComponentProps, IUser} from 'superdesk-api';
import {IUserSignOff} from '../../interfaces';
import {IAuthorSignOffData} from '../../interfaces';
import {superdesk} from '../../superdesk';

import {loadUsersFromPublishSignOff, getSignOffDetails} from '../../utils';
import {loadUsersFromPublishSignOff, getSignOffDetails, viewSignOffApprovalForm} from '../../utils';

import {IconLabel, ToggleBox} from 'superdesk-ui-framework/react';
import {SignOffListItem} from '../SignOffListItem';
import {SignOffRequestDetails} from '../SignOffRequestDetails';

type IProps = IPreviewComponentProps<IUserSignOff | null>;
type IProps = IPreviewComponentProps<IAuthorSignOffData | null>;
type ISignOffState = 'completed' | 'partially' | 'none';

function getSignOffStateLabel(state: ISignOffState): string {
Expand Down Expand Up @@ -88,9 +88,18 @@ export class UserSignOffPreview extends React.PureComponent<IProps, IState> {
user={this.state.users[signOffData.user_id]}
readOnly={true}
appendContentDivider={index < publishSignOff.sign_offs.length - 1}
fundingSource={signOffData.funding_source}
affiliation={signOffData.affiliation}
email={signOffData.author.email}
date={signOffData.sign_date}
buttonProps={[{
type: 'success',
text: gettext('View Form'),
icon: 'external',
onClick: viewSignOffApprovalForm.bind(
undefined,
this.props.item._id,
signOffData.user_id,
)
}]}
/>
)
))}
Expand Down
31 changes: 26 additions & 5 deletions client/extensions/tga-sign-off/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
import {IEditorComponentProps, IUser} from 'superdesk-api';

export interface IUserSignOff {
requester_id: undefined;
export interface IAuthorSignOffData {
user_id: IUser['_id'];
sign_date: string;
version_signed: number;

article_name: string;
funding_source: string;
affiliation: string;
consent_publish: boolean;
consent_disclosure: boolean;
copyright_terms: string;

author: {
name: string;
title: string;
institute: string;
email: string;
country: string;
orcid_id?: string;
};

warrants: {
no_copyright_infringements: boolean;
indemnify_360_against_loss: boolean;
ready_for_publishing: boolean;
};
consent: {
signature: string;
contact: boolean;
personal_information: boolean;
multimedia_usage: boolean;
};
}

export interface IPublishSignOff {
Expand All @@ -19,7 +40,7 @@ export interface IPublishSignOff {
sent: string; // datetime string
expires: string; // datetime string
}>;
sign_offs: Array<IUserSignOff>;
sign_offs: Array<IAuthorSignOffData>;
}

export type IEditorProps = IEditorComponentProps<IPublishSignOff | null, {}>;
21 changes: 20 additions & 1 deletion client/extensions/tga-sign-off/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@ export function hasUserSignedOff(item: IArticle): boolean {

for (let i = 0; i < publishSignOff.sign_offs.length; i++) {
const signOff = publishSignOff.sign_offs[i];
const {warrants, consent} = signOff;

if (signOff.consent_publish === false || signOff.consent_disclosure === false) {
if (warrants.no_copyright_infringements !== true ||
warrants.indemnify_360_against_loss !== true ||
warrants.ready_for_publishing !== true
) {
return false;
} else if (consent.contact !== true ||
consent.personal_information !== true ||
consent.multimedia_usage != true
) {
return false;
} else if (signOff.funding_source.trim().length === 0 || signOff.affiliation.trim().length === 0) {
return false;
Expand Down Expand Up @@ -94,3 +103,13 @@ export function getSignOffDetails(item: IArticle, users: {[userId: string]: IUse
requestUser,
};
}

export function viewSignOffApprovalForm(itemId: IArticle['_id'], userId: IUser['_id']) {
const baseUrl = superdesk.instance.config.server.url;

window.open(
`${baseUrl}/sign_off_requests/${itemId}/${userId}/view`,
'signOffForm',
'popup'
);
}
Loading

0 comments on commit 64acbef

Please sign in to comment.