diff --git a/app/models/registration-schema.ts b/app/models/registration-schema.ts index 25194f299..c264e3c09 100644 --- a/app/models/registration-schema.ts +++ b/app/models/registration-schema.ts @@ -31,6 +31,7 @@ export interface Page { questions: Question[]; type?: 'object'; description?: string; + clipboardCopyPaste: boolean; } export interface Schema { diff --git a/app/models/schema-block.ts b/app/models/schema-block.ts index ede4f06f5..dfd8474e6 100644 --- a/app/models/schema-block.ts +++ b/app/models/schema-block.ts @@ -22,9 +22,15 @@ export default class SchemaBlockModel extends OsfModel implements SchemaBlock { @attr('number') index?: number; @attr('string') pattern?: string; @attr('boolean') spaceNormalization?: boolean; - @attr('boolean') autoDate?: boolean; - @attr('boolean') autoTitle?: boolean; - @attr('boolean') hideProjectmetadata?: boolean; + @attr('string') getRetrievalTitle?: string; + @attr('string') getRetrievalDate?: string; + @attr('boolean') concealmentPageNavigator?: boolean; + @attr('string') requiredAllCheck?: string; + @attr('boolean') multiLanguage?: boolean; + @attr('string') getRetrievalVersion?: string; + @attr('boolean') getEdit?: boolean; + @attr('boolean') sentence?: boolean; + @attr('string') rowAdditionCaption?: string; @belongsTo('registration-schema', { inverse: 'schemaBlocks', async: false }) schema?: RegistrationSchemaModel; diff --git a/app/packages/registration-schema/get-pages.ts b/app/packages/registration-schema/get-pages.ts index c458942be..de58f2762 100644 --- a/app/packages/registration-schema/get-pages.ts +++ b/app/packages/registration-schema/get-pages.ts @@ -3,15 +3,16 @@ import { SchemaBlock } from 'ember-osf-web/packages/registration-schema'; export function getPages(blocks: SchemaBlock[]) { const pageArray = blocks.reduce( (pages, block) => { + // instantiate first page if the schema doesn't start with a page-heading if (pages.length === 0 && block.blockType !== 'page-heading' - && (block.hideProjectmetadata === true || block.hideProjectmetadata === undefined)) { + && (block.concealmentPageNavigator === true || block.concealmentPageNavigator === undefined)) { const blankPage: SchemaBlock[] = []; pages.push(blankPage); } - const lastPage: SchemaBlock[] = pages.slice(-1)[0] || []; + const lastPage: SchemaBlock[] = pages.slice(-1)[0]; if (block.blockType === 'page-heading' - && (block.hideProjectmetadata === false || block.hideProjectmetadata === undefined)) { + && (block.concealmentPageNavigator === false || block.concealmentPageNavigator === undefined)) { pages.push([block]); } else { lastPage.push(block); diff --git a/app/packages/registration-schema/get-schema-block-group.ts b/app/packages/registration-schema/get-schema-block-group.ts index d459c262f..207275d62 100644 --- a/app/packages/registration-schema/get-schema-block-group.ts +++ b/app/packages/registration-schema/get-schema-block-group.ts @@ -43,6 +43,7 @@ export function getSchemaBlockGroups(blocks: SchemaBlock[] | undefined) { case 'jgn-program-name-ja-input': case 'jgn-program-name-en-input': case 'e-rad-award-funder-input': + case 'single-select-pulldown-input': case 'pulldown-input': case 'e-rad-award-number-input': case 'e-rad-award-title-ja-input': @@ -53,6 +54,7 @@ export function getSchemaBlockGroups(blocks: SchemaBlock[] | undefined) { case 'e-rad-researcher-name-en-input': case 'e-rad-bunnya-input': case 'file-metadata-input': + case 'ad-metadata-input': case 'date-input': case 'section-heading': case 'subsection-heading': diff --git a/app/packages/registration-schema/index.ts b/app/packages/registration-schema/index.ts index b09e7121f..d8f93c645 100644 --- a/app/packages/registration-schema/index.ts +++ b/app/packages/registration-schema/index.ts @@ -2,7 +2,12 @@ export { getPages } from './get-pages'; export { getSchemaBlockGroups } from './get-schema-block-group'; export { SchemaBlock, SchemaBlockType } from './schema-block'; export { SchemaBlockGroup } from './schema-block-group'; -export { buildValidation, buildMetadataValidations, setupEventForSyncValidation } from './validations'; +export { + buildValidation, + buildMetadataValidations, + setupEventForSyncValidation, + setupEventForSyncValidation2, +} from './validations'; export { FileReference, RegistrationResponse, diff --git a/app/packages/registration-schema/page-manager.ts b/app/packages/registration-schema/page-manager.ts index b801a28ce..a7a099372 100644 --- a/app/packages/registration-schema/page-manager.ts +++ b/app/packages/registration-schema/page-manager.ts @@ -10,6 +10,7 @@ import { SchemaBlock, SchemaBlockGroup, setupEventForSyncValidation, + setupEventForSyncValidation2, } from 'ember-osf-web/packages/registration-schema'; import { RegistrationResponse } from 'ember-osf-web/packages/registration-schema/registration-response'; @@ -17,14 +18,14 @@ export class PageManager { changeset?: ChangesetDef; schemaBlockGroups?: SchemaBlockGroup[]; pageHeadingText?: string; - hideProjectmetadata?: boolean; + concealmentPageNavigator?: boolean; isVisited?: boolean; constructor(pageSchemaBlocks: SchemaBlock[], registrationResponses: RegistrationResponse, node?: NodeModel) { this.schemaBlockGroups = getSchemaBlockGroups(pageSchemaBlocks); if (this.schemaBlockGroups) { this.pageHeadingText = this.schemaBlockGroups[0].labelBlock!.displayText!; - this.hideProjectmetadata = this.schemaBlockGroups[0].labelBlock!.hideProjectmetadata!; + this.concealmentPageNavigator = this.schemaBlockGroups[0].labelBlock!.concealmentPageNavigator!; this.isVisited = this.schemaBlockGroups.some( ({ registrationResponseKey: key }) => Boolean(key && (key in registrationResponses)), @@ -36,8 +37,11 @@ export class PageManager { lookupValidator(validations), validations, ) as ChangesetDef; + setupEventForSyncValidation(this.changeset, this.schemaBlockGroups); + setupEventForSyncValidation2(this.changeset, this.schemaBlockGroups); + if (this.isVisited) { this.changeset.validate(); } diff --git a/app/packages/registration-schema/schema-block.ts b/app/packages/registration-schema/schema-block.ts index b99203c94..26f3b57bb 100644 --- a/app/packages/registration-schema/schema-block.ts +++ b/app/packages/registration-schema/schema-block.ts @@ -17,6 +17,7 @@ export type SchemaBlockType = 'jgn-program-name-ja-input' | 'jgn-program-name-en-input' | 'e-rad-award-funder-input' | + 'single-select-pulldown-input' | 'pulldown-input' | 'e-rad-award-number-input' | 'e-rad-award-title-ja-input' | @@ -27,6 +28,7 @@ export type SchemaBlockType = 'e-rad-researcher-name-en-input' | 'e-rad-bunnya-input' | 'file-metadata-input' | + 'ad-metadata-input' | 'date-input' | 'array-input'; @@ -44,7 +46,12 @@ export interface SchemaBlock { index?: number; pattern?: string; spaceNormalization?: boolean; - autoDate?: boolean; - autoTitle?: boolean; hideProjectmetadata?: boolean; + getRetrievalTitle?: string; + getRetrievalDate?: string; + concealmentPageNavigator?: boolean; + requiredAllCheck?: string; + multiLanguage?: boolean; + getRetrievalVersion?: string; + rowAdditionCaption?: string; } diff --git a/app/packages/registration-schema/validations.ts b/app/packages/registration-schema/validations.ts index e844e3476..362a21ca9 100644 --- a/app/packages/registration-schema/validations.ts +++ b/app/packages/registration-schema/validations.ts @@ -161,6 +161,47 @@ export function setupEventForSyncValidation(changeset: ChangesetDef, groups: Sch }); } +export function setupEventForSyncValidation2(changeset: ChangesetDef, groups: SchemaBlockGroup[]) { + const requiredAllCheckGroups = groups + // ignore GRDM file specific fields + .filter((group: SchemaBlockGroup) => !group.registrationResponseKey + || !group.registrationResponseKey.match(/^__responseKey_grdm-file:.+$/)) + .filter((group: SchemaBlockGroup) => group.inputBlock && group.inputBlock.requiredAllCheck); + + let isProcesing = false; + + changeset.on('afterValidation', () => { + if (isProcesing) { + return; + } + isProcesing = true; + + try { + const checkboxList = requiredAllCheckGroups.map(group => { + const registrationResponseKey: string = group.registrationResponseKey || ''; + const value = changeset.get(registrationResponseKey); + return Array.isArray(value) && value.length === 1; + }); + + requiredAllCheckGroups + .forEach(group => { + if (!checkboxList.includes(false)) { + const todayDate = `${new Date().getFullYear()}/${ + String(new Date().getMonth() + 1).padStart(2, '0') + }/${ + String(new Date().getDate()).padStart(2, '0') + }`; + changeset.set(`__responseKey_${group.inputBlock!.requiredAllCheck}`, todayDate); + } else { + changeset.set(`__responseKey_${group.inputBlock!.requiredAllCheck}`, ''); + } + }); + } finally { + isProcesing = false; + } + }); +} + export function validateNodeLicense() { return async (_: unknown, __: unknown, ___: unknown, changes: DraftRegistration, content: DraftRegistration) => { let validateLicenseTarget = await content.license; diff --git a/lib/osf-components/addon/components/contributor-list/component.ts b/lib/osf-components/addon/components/contributor-list/component.ts index 595e5bc45..ff6795b13 100644 --- a/lib/osf-components/addon/components/contributor-list/component.ts +++ b/lib/osf-components/addon/components/contributor-list/component.ts @@ -60,7 +60,15 @@ export default class ContributorList extends Component { this.set('totalContributors', nextPage.meta.total); } else { this.set('page', 1); - const firstPage = yield this.node.bibliographicContributors; + const firstPage = yield this.node.queryHasMany( + 'bibliographicContributors', + { + fields: { + users: 'full_name,given_name,family_name,id,links', + }, + page: { size: 10 }, + }, + ); this.setProperties({ displayedContributors: firstPage.toArray(), totalContributors: firstPage.meta.total, diff --git a/lib/osf-components/addon/components/form-controls/template.hbs b/lib/osf-components/addon/components/form-controls/template.hbs index d8cb46a9f..70454fe6e 100644 --- a/lib/osf-components/addon/components/form-controls/template.hbs +++ b/lib/osf-components/addon/components/form-controls/template.hbs @@ -14,13 +14,6 @@ shouldShowMessages=this.shouldShowMessages disabled=this.disabled ) - autodate=( - component - 'validated-input/autodate' - changeset=@changeset - shouldShowMessages=this.shouldShowMessages - disabled=this.disabled - ) recaptcha=( component 'validated-input/recaptcha' diff --git a/lib/osf-components/addon/components/osf-layout/registries-side-nav/component.ts b/lib/osf-components/addon/components/osf-layout/registries-side-nav/component.ts index 4aeeb128b..a182e9bc1 100644 --- a/lib/osf-components/addon/components/osf-layout/registries-side-nav/component.ts +++ b/lib/osf-components/addon/components/osf-layout/registries-side-nav/component.ts @@ -5,7 +5,12 @@ import { and, or } from '@ember/object/computed'; import { inject as service } from '@ember/service'; import Media from 'ember-responsive'; +import DS from 'ember-data'; +import Intl from 'ember-intl/services/intl'; import { layout } from 'ember-osf-web/decorators/component'; +import DraftRegistration from 'ember-osf-web/models/draft-registration'; +import CurrentUser from 'ember-osf-web/services/current-user'; +import Toast from 'ember-toastr/services/toast'; import styles from './styles'; import template from './template'; @@ -13,7 +18,16 @@ import template from './template'; @tagName('') @layout(template, styles) export default class RegistriesSideNav extends Component { + @service store!: DS.Store; + draftRegistrations: DraftRegistration[] = []; + // registrationSchema: RegistrationSchema[] = []; + @service toast!: Toast; + format?: string = ''; + @service media!: Media; + @service intl!: Intl; + @service currentUser!: CurrentUser; + // changeset!: ChangesetDef; // Optional params onLinkClicked?: () => void; @@ -27,8 +41,84 @@ export default class RegistriesSideNav extends Component { @and('isCollapseAllowed', 'shouldCollapse') isCollapsed!: boolean; + @service router!: any; + disableButtons = false; + pageTitle = ''; + jsonData = ''; + + constructor(...args: any[]) { + super(...args); + this.handleRouteChange(); + if (this.router && typeof this.router.on === 'function') { + this.router.on('routeDidChange', this.handleRouteChange.bind(this)); + } + } + @action toggle() { this.toggleProperty('shouldCollapse'); } + + @action + async handleRouteChange() { + const currentUrl = window.location.href; + const urlParts = currentUrl.split('/'); + const lastPartWithQuery = urlParts[urlParts.length - 1]; + const metadataTitle = lastPartWithQuery.split('?')[0]; + const cleanedTitle = metadataTitle.replace(/^\d+-/, ''); + const title = decodeURIComponent(cleanedTitle.replace(/-/g, ' ')); + this.set('pageTitle', title.trim().toLowerCase()); + const allSchemas = await this.store.findAll('registration-schema'); + const matchedSchema = allSchemas.find((schema: any) => schema.schema.pages.some((page: any) => ( + page.title.trim().toLowerCase() === title.trim().toLowerCase() + && page.clipboardCopyPaste === false))); + + if (matchedSchema) { + this.set('disableButtons', true); + } else { + this.set('disableButtons', false); + } + } + + @action + async copyToClipboard() { + const currentUrl = window.location.href; + const idRegex = /\/drafts\/([a-f0-9]{24})/; + const match = currentUrl.match(idRegex); + if (match && match[1]) { + const draftId = match[1]; + + const draftRegistration = await this.store.findRecord('draft-registration', draftId); + + if (draftRegistration) { + const registrationMetadata = await draftRegistration.registrationMetadata; + const metadata: { [key: string]: any } = {}; + const registrationSchema = await draftRegistration.registrationSchema; + for (const page of registrationSchema.schema.pages) { + if (page.title.trim().toLowerCase() !== this.pageTitle && !page.clipboardCopyPaste) { + continue; + } + + for (const question of page.questions) { + Object.keys(registrationMetadata).forEach(key => { + if (key === question.qid && !key.startsWith('grdm-')) { + if (question.format === 'multiselect' && registrationMetadata[key].value === '') { + metadata[key] = []; + } else { + metadata[key] = registrationMetadata[key].value; + } + } + }); + } + } + this.jsonData = JSON.stringify(metadata); + if (this.jsonData === '{}' || Object.keys(JSON.parse(this.jsonData)).length === 0) { + this.toast.warning(this.intl.t('registries.drafts.draft.form.warning_noautosave')); + } else { + await navigator.clipboard.writeText(this.jsonData); + this.toast.success(this.intl.t('registries.drafts.draft.form.clipboard_copied')); + } + } + } + } } diff --git a/lib/osf-components/addon/components/osf-layout/registries-side-nav/label/styles.scss b/lib/osf-components/addon/components/osf-layout/registries-side-nav/label/styles.scss index 7725fff7f..8610e153d 100644 --- a/lib/osf-components/addon/components/osf-layout/registries-side-nav/label/styles.scss +++ b/lib/osf-components/addon/components/osf-layout/registries-side-nav/label/styles.scss @@ -1,10 +1,11 @@ .LabelWrapper { justify-content: space-between; - display: inline-flex; + display: flex; width: 100%; padding-left: 10px; font-weight: 700; - white-space: inherit; + white-space: normal; + word-wrap: break-word; overflow: hidden; &:hover { @@ -16,6 +17,8 @@ float: left; overflow: hidden; text-overflow: ellipsis; + white-space: normal; + word-wrap: break-word; &:hover { overflow: visible; @@ -24,4 +27,7 @@ .Count { float: right; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } diff --git a/lib/osf-components/addon/components/osf-layout/registries-side-nav/template.hbs b/lib/osf-components/addon/components/osf-layout/registries-side-nav/template.hbs index 3c41565ce..44348815a 100644 --- a/lib/osf-components/addon/components/osf-layout/registries-side-nav/template.hbs +++ b/lib/osf-components/addon/components/osf-layout/registries-side-nav/template.hbs @@ -38,4 +38,23 @@ {{/let}} {{/if}} + + {{!-- model1 :{{@model}} + model2 : {{model}} + {{#each @model as |item index|}} + {{#if (eq index 1)}} +

test >>{{item}}

+ {{/if}} + {{/each}} + test --}} + + {{t 'registries.drafts.draft.form.copy_to_clipboard'}} + + diff --git a/lib/osf-components/addon/components/registries/registration-form-navigation-dropdown/template.hbs b/lib/osf-components/addon/components/registries/registration-form-navigation-dropdown/template.hbs index 2e0df5bd2..576899fe8 100644 --- a/lib/osf-components/addon/components/registries/registration-form-navigation-dropdown/template.hbs +++ b/lib/osf-components/addon/components/registries/registration-form-navigation-dropdown/template.hbs @@ -60,16 +60,18 @@ {{/each}} {{/if}} {{#each this.localizedBlocksWithAnchor as |block|}} -
  • - - {{block.localizedDisplayText}} - -
  • + {{#unless block.model.concealmentPageNavigator}} +
  • + + {{block.localizedDisplayText}} + +
  • + {{/unless}} {{/each}} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/files/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/files/template.hbs index e9f22edca..0a53fb0d4 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/files/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/files/template.hbs @@ -1,13 +1,15 @@ -

    - {{t 'osf-components.registries.schema-block-renderer/editable/files.instructions' - projectOrComponent=(if @node.isRoot 'project' 'component') - nodeUrl=this.nodeUrl - htmlSafe=true - }} -

    +{{#if (not @schemaBlock.sentence)}} +

    + {{t 'osf-components.registries.schema-block-renderer/editable/files.instructions' + projectOrComponent=(if @node.isRoot 'project' 'component') + nodeUrl=this.nodeUrl + htmlSafe=true + }} +

    +{{/if}} void; + onMetadataInput!: () => void; + schemaBlockGroup!: SchemaBlockGroup; + schemaBlock!: SchemaBlock; + node!: NodeModel; + + subChangesets: ChangesetDef[] = []; + + didReceiveAttrs() { + const rowAdditionCaption = this.schemaBlock.rowAdditionCaption || ''; + + this.schemaBlock.rowAdditionCaption = this.getLocalizedText(rowAdditionCaption); + + const raw = this.changeset.get(this.valuePath); + if (raw) { + const prefix = `${this.valuePath}|`; + const values = JSON.parse(raw); + const subChangesets: ChangesetDef[] = values.map((row: Array<{key: string, value: any}>) => { + const subChangeset = this.createSubChangeset(); + Object.entries(row).forEach(([k, v]) => { + const key2 = `${prefix}${k}`; + subChangeset.set(key2, v); + }); + subChangeset.on('afterValidation', () => { + this.save(this.get('subChangesets')); + }); + return subChangeset; + }); + this.set('subChangesets', subChangesets); + } else { + this.set('subChangesets', []); + } + } + + save(subChangesets: ChangesetDef[]) { + const prefix = `${this.valuePath}|`; + const allChanges = subChangesets.map(changeset => { + const changes: Array<{key: string, value: any}> = changeset.changes as any; + const row: {[key: string]: any} = {}; + changes.forEach(({ key, value }) => { + assert( + `Sub changeset key ${key} requires starting with parent key ${prefix}`, + key.startsWith(prefix), + ); + const key2 = key.substr(prefix.length); + row[key2] = value; + }); + return row; + }).filter(changes => Object.keys(changes).length); + // todo: exclude rows where all values are empty + this.changeset.set(this.valuePath, JSON.stringify(allChanges)); + } + + createSubChangeset() { + const validations = buildValidation(this.schemaBlockGroup.children!, this.node); + const subChangeset = new Changeset( + {}, + lookupValidator(validations), + validations, + ) as ChangesetDef; + // todo: setupEventForSyncValidation + return subChangeset; + } + + @action + onAdd() { + const subChangeset = this.createSubChangeset(); + this.set('subChangesets', [...this.get('subChangesets'), subChangeset]); + subChangeset.on('afterValidation', () => { + this.save(this.get('subChangesets')); + }); + } + + @action + onRemove(subChangeset: ChangesetDef) { + const newSubChangesets = this.get('subChangesets').filter(c => c !== subChangeset); + this.set('subChangesets', newSubChangesets); + this.save(newSubChangesets); + } + + getLocalizedText(text: string) { + if (!text.includes('|')) { + return text; + } + const texts = text.split('|'); + if (this.intl.locale.includes('ja')) { + return texts[0]; + } + return texts[1]; + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/styles.scss new file mode 100644 index 000000000..f29e4bdb2 --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/styles.scss @@ -0,0 +1,49 @@ +.file-metadata-input-container { + width: 100%; + border: 1px solid #eee; + padding: 0.5em; +} + +.file-metadata-input-files { + border: 1px solid #eee; +} + +.file-metadata-input-files th { + border: 1px solid #eee; + background: #f5f5f5; + height: 35px; +} + +.file-metadata-input-files td { + border-top: 1px solid #eee; + height: 35px; +} + +.file-metadata-input-files .file-metadata-path { + max-width: 250px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-files .file-metadata-title { + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-files .file-metadata-manager { + max-width: 50px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-edit-button { + padding: 0 !important; +} + +.file-metadata-input-buttons { + margin-bottom: 4px; +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/template.hbs new file mode 100644 index 000000000..0551275fe --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/template.hbs @@ -0,0 +1,75 @@ + + {{#if this.fileEntries}} + + + + + + + + + {{#each this.fileEntries as |fileEntry|}} + {{#if fileEntry.visible}} + + + + + {{/if}} + {{/each}} + +
    + + {{t 'metadata.file-metadata-input.columns.path'}} +
    + {{#if fileEntry.added}} + + {{else if fileEntry.hasProject}} + + {{/if}} + +

    + {{#if fileEntry.folder}} + {{#if fileEntry.folderExpanded}} + + {{else}} + + {{/if}} + + {{else}} + + {{/if}} + {{fileEntry.lastPart}} +

    +
    + {{else}} + + {{/if}} +
    \ No newline at end of file diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/component.ts index 4b2a45a66..e151ca58b 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/component.ts +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/component.ts @@ -4,13 +4,17 @@ import Component from '@ember/component'; import { assert } from '@ember/debug'; import { action } from '@ember/object'; import { alias } from '@ember/object/computed'; +import { inject as service } from '@ember/service'; + import Changeset from 'ember-changeset'; import lookupValidator from 'ember-changeset-validations'; import { ChangesetDef } from 'ember-changeset/types'; +import Intl from 'ember-intl/services/intl'; import { layout } from 'ember-osf-web/decorators/component'; import NodeModel from 'ember-osf-web/models/node'; -import { buildValidation, SchemaBlockGroup } from 'ember-osf-web/packages/registration-schema'; +import { buildValidation, SchemaBlock, SchemaBlockGroup } from 'ember-osf-web/packages/registration-schema'; import DraftRegistrationManager from 'registries/drafts/draft/draft-registration-manager'; + import styles from './styles'; import template from './template'; @@ -21,17 +25,23 @@ export default class ArrayInput extends Component { changeset!: ChangesetDef; metadataChangeset!: ChangesetDef; draftManager!: DraftRegistrationManager; + @service intl!: Intl; @alias('schemaBlock.registrationResponseKey') valuePath!: string; onInput!: () => void; onMetadataInput!: () => void; schemaBlockGroup!: SchemaBlockGroup; + schemaBlock!: SchemaBlock; node!: NodeModel; subChangesets: ChangesetDef[] = []; didReceiveAttrs() { + const rowAdditionCaption = this.schemaBlock.rowAdditionCaption || ''; + + this.schemaBlock.rowAdditionCaption = this.getLocalizedText(rowAdditionCaption); + const raw = this.changeset.get(this.valuePath); if (raw) { const prefix = `${this.valuePath}|`; @@ -98,4 +108,15 @@ export default class ArrayInput extends Component { this.set('subChangesets', newSubChangesets); this.save(newSubChangesets); } + + getLocalizedText(text: string) { + if (!text.includes('|')) { + return text; + } + const texts = text.split('|'); + if (this.intl.locale.includes('ja')) { + return texts[0]; + } + return texts[1]; + } } diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/template.hbs index 3bf4592c3..6c41fd193 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/array-input/template.hbs @@ -23,7 +23,7 @@ - {{t 'metadata.array-input.remove-item'}} + {{this.schemaBlock.rowAdditionCaption}}{{t 'metadata.array-input.remove-item'}} {{/each}} @@ -32,7 +32,7 @@ @type='primary' @onClick={{action this.onAdd}} > - {{t 'metadata.array-input.add-item'}} + {{this.schemaBlock.rowAdditionCaption}}{{t 'metadata.array-input.add-item'}} \ No newline at end of file diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-number-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-number-input/component.ts index 8756ce0e8..440b07045 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-number-input/component.ts +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-number-input/component.ts @@ -54,6 +54,7 @@ export default class ERadAwardNumberInput extends Component { if (eradRecord) { kadaiId = eradRecord.kadai_id; this.updateCode('e-rad-award-funder-input', eradRecord.haibunkikan_cd); + this.updateCode('single-select-pulldown-input', eradRecord.haibunkikan_cd); this.updateCode('e-rad-award-field-input', eradRecord.bunya_cd); this.changeset.set( this.draftManager.getResponseKeyByBlockType('e-rad-award-title-ja-input'), diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-en-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-en-input/template.hbs index 23e459a95..25af56ad4 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-en-input/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-en-input/template.hbs @@ -10,7 +10,6 @@ local-class='schema-block-input' @uniqueID={{@uniqueID}} @valuePath={{@schemaBlock.registrationResponseKey}} - @onChange={{action this.onInput2}} @onKeyUp={{action this.onInput2}} @placeholder=' ' /> diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-ja-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-ja-input/template.hbs index 55c15c85c..283351ef3 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-ja-input/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/e-rad-award-title-ja-input/template.hbs @@ -10,7 +10,6 @@ local-class='schema-block-input' @uniqueID={{@uniqueID}} @valuePath={{@schemaBlock.registrationResponseKey}} - @onChange={{action this.onInput2}} @onKeyUp={{action this.onInput2}} @placeholder=' ' /> diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/japan-grant-number-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/japan-grant-number-input/component.ts index eb931644c..5bc8f34db 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/japan-grant-number-input/component.ts +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/japan-grant-number-input/component.ts @@ -54,7 +54,7 @@ export default class JapanGrantNumberInput extends Component { if (eradRecord) { kadaiId = eradRecord.japan_grant_number; this.updateCode('e-rad-award-funder-input', eradRecord.haibunkikan_cd); - this.updateCode('pulldown-input', eradRecord.haibunkikan_cd); + this.updateCode('single-select-pulldown-input', eradRecord.haibunkikan_cd); this.updateCode('e-rad-award-field-input', eradRecord.bunya_cd); if (eradRecord.funding_stream_code) { const key = this.getResponseKeyByBlockType('funding-stream-code-input'); diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.ts new file mode 100644 index 000000000..6562416a5 --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.ts @@ -0,0 +1,85 @@ +import { tagName } from '@ember-decorators/component'; +import Component from '@ember/component'; +import { assert } from '@ember/debug'; +import { action, computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; +import { inject as service } from '@ember/service'; + +import { ChangesetDef } from 'ember-changeset/types'; +import Intl from 'ember-intl/services/intl'; + +import { layout } from 'ember-osf-web/decorators/component'; +import { SchemaBlock } from 'ember-osf-web/packages/registration-schema'; + +import template from './template'; + +@layout(template) +@tagName('') +export default class SingleSelectPulldownInput extends Component { + @service intl!: Intl; + // Required param + optionBlocks!: SchemaBlock[]; + changeset!: ChangesetDef; + + @alias('schemaBlock.registrationResponseKey') + valuePath!: string; + onInput!: () => void; + onMetadataInput!: () => void; + + anotherOption?: string; + + didReceiveAttrs() { + assert( + 'SchemaBlockRenderer::Editable::SingleSelectPulldownInput requires optionBlocks to render', + Boolean(this.optionBlocks), + ); + } + + @computed('optionBlocks.[]', 'anotherOption') + get optionBlockValues() { + const options = this.optionBlocks + .map(item => this.getLocalizedItemText(item)); + if (this.anotherOption) { + options.push(this.anotherOption); + } + return options; + } + + @action + onChange(option: string) { + const code = (option || '').trim(); + const item = this.optionBlocks.find(b => code === b.displayText); + const result = item ? item.displayText : option; + this.changeset.set(this.valuePath, result); + this.onMetadataInput(); + this.onInput(); + this.set('anotherOption', null); + } + + @action + onInputSearch(text: string) { + if (!this.optionBlocks.find(item => item.displayText === text || this.getLocalizedItemText(item) === text)) { + this.set('anotherOption', text); + } + return true; + } + + getLocalizedItemText(item: SchemaBlock) { + const text = item.helpText || item.displayText; + if (text === undefined) { + return item.displayText; + } + return `${item.displayText}`; + } + + getLocalizedText(text: string) { + if (!text.includes('|')) { + return text; + } + const texts = text.split('|'); + if (this.intl.locale.includes('ja')) { + return texts[0]; + } + return texts[1]; + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/styles.scss new file mode 100644 index 000000000..462216f6a --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/styles.scss @@ -0,0 +1,9 @@ +.schema-block-input { + :global(input) { + height: 40px; + background-color: $color-bg-gray-blue-light; + color: $color-text-gray-blue; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2); + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/template.hbs new file mode 100644 index 000000000..4fef23b8f --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/template.hbs @@ -0,0 +1,26 @@ + + + + {{option}} + + + + \ No newline at end of file diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.ts new file mode 100644 index 000000000..6562416a5 --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.ts @@ -0,0 +1,85 @@ +import { tagName } from '@ember-decorators/component'; +import Component from '@ember/component'; +import { assert } from '@ember/debug'; +import { action, computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; +import { inject as service } from '@ember/service'; + +import { ChangesetDef } from 'ember-changeset/types'; +import Intl from 'ember-intl/services/intl'; + +import { layout } from 'ember-osf-web/decorators/component'; +import { SchemaBlock } from 'ember-osf-web/packages/registration-schema'; + +import template from './template'; + +@layout(template) +@tagName('') +export default class SingleSelectPulldownInput extends Component { + @service intl!: Intl; + // Required param + optionBlocks!: SchemaBlock[]; + changeset!: ChangesetDef; + + @alias('schemaBlock.registrationResponseKey') + valuePath!: string; + onInput!: () => void; + onMetadataInput!: () => void; + + anotherOption?: string; + + didReceiveAttrs() { + assert( + 'SchemaBlockRenderer::Editable::SingleSelectPulldownInput requires optionBlocks to render', + Boolean(this.optionBlocks), + ); + } + + @computed('optionBlocks.[]', 'anotherOption') + get optionBlockValues() { + const options = this.optionBlocks + .map(item => this.getLocalizedItemText(item)); + if (this.anotherOption) { + options.push(this.anotherOption); + } + return options; + } + + @action + onChange(option: string) { + const code = (option || '').trim(); + const item = this.optionBlocks.find(b => code === b.displayText); + const result = item ? item.displayText : option; + this.changeset.set(this.valuePath, result); + this.onMetadataInput(); + this.onInput(); + this.set('anotherOption', null); + } + + @action + onInputSearch(text: string) { + if (!this.optionBlocks.find(item => item.displayText === text || this.getLocalizedItemText(item) === text)) { + this.set('anotherOption', text); + } + return true; + } + + getLocalizedItemText(item: SchemaBlock) { + const text = item.helpText || item.displayText; + if (text === undefined) { + return item.displayText; + } + return `${item.displayText}`; + } + + getLocalizedText(text: string) { + if (!text.includes('|')) { + return text; + } + const texts = text.split('|'); + if (this.intl.locale.includes('ja')) { + return texts[0]; + } + return texts[1]; + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/styles.scss new file mode 100644 index 000000000..462216f6a --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/styles.scss @@ -0,0 +1,9 @@ +.schema-block-input { + :global(input) { + height: 40px; + background-color: $color-bg-gray-blue-light; + color: $color-text-gray-blue; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2); + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/template.hbs new file mode 100644 index 000000000..4fef23b8f --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/template.hbs @@ -0,0 +1,26 @@ + + + + {{option}} + + + + \ No newline at end of file diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/text/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/text/template.hbs index 9322a3674..c7f769ca9 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/editable/text/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/editable/text/template.hbs @@ -11,9 +11,14 @@ @uniqueID={{@uniqueID}} @valuePath={{@schemaBlock.registrationResponseKey}} @onKeyUp={{@onInput}} - @autoTitle={{@schemaBlock.autoTitle}} - @autoDate={{@schemaBlock.autoDate}} + @getRetrievalTitle={{@schemaBlock.getRetrievalTitle}} + @getRetrievalDate={{@schemaBlock.getRetrievalDate}} + @getRetrievalVersion={{@schemaBlock.getRetrievalVersion}} + @getEdit={{@schemaBlock.getEdit}} @title={{@draftManager.node.title}} + @nodeId={{@node.id}} + @datetimeInitiated={{@draftManager.draftRegistration.datetimeInitiated}} + @datetimeUpdated={{@draftManager.draftRegistration.datetimeUpdated}} @placeholder=' ' /> diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/component.ts index 42b7e43f0..6ae178992 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/component.ts +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/component.ts @@ -49,6 +49,25 @@ export default class LabelContent extends Component { return this.getLocalizedText(text); } + @computed('localizedHelpText') + get localizedHelpTextLines() { + const text = this.localizedHelpText; + if (!text) { + return []; + } + + return text.split('\n').map(line => { + const urlRegex = /(https?:\/\/[^\s]+)/g; + + const parts = line.split(urlRegex).map(part => ({ + content: part, + isLink: part.startsWith('https://'), + })); + + return parts; + }); + } + getLocalizedText(text: string) { if (!text.includes('|')) { return text; diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/styles.scss index 873f7ddf6..30c9d8563 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/styles.scss +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/styles.scss @@ -1,7 +1,6 @@ .DisplayText { white-space: pre-wrap; display: inline-block; - margin: 0; } .Required { @@ -13,8 +12,8 @@ .HelpText { composes: Element from '../../styles'; - white-space: pre-wrap; font-weight: 400; + margin-top: 0; } .ExampleButton { @@ -37,3 +36,9 @@ white-space: pre-wrap; font-weight: 400; } + + +.HelpTextLine { + font-weight: normal !important; + margin-bottom: 0; +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/template.hbs index 3901cadcb..0af64917a 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/label/label-content/template.hbs @@ -8,9 +8,26 @@ {{~/if~}}

    {{#if @isEditableForm}} -

    - {{~this.localizedHelpText~}} -

    +
    + {{#each this.localizedHelpTextLines as |lineParts|}} +

    + {{#each lineParts as |part|}} + {{#if part.isLink}} + + {{part.content}} + + {{else}} + {{part.content}} + {{/if}} + {{/each}} +

    + {{/each}} +
    + {{#if @schemaBlock.exampleText}} { + const parts = line.split(urlPattern).map(part => ( + urlPattern.test(part) + ? { type: 'link', content: part.trim() } + : { type: 'text', content: part.trim() } + )); + return parts; + }); + + return lines; } getLocalizedText(text: string) { diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/styles.scss index cff4b6753..907b577b0 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/styles.scss +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/styles.scss @@ -5,5 +5,5 @@ } .PageHeading_helper { - margin-top: 10px; + margin-bottom: 0; } diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/template.hbs index 4e43c5f7f..814ec79eb 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/page-heading/template.hbs @@ -1,4 +1,4 @@ -{{#unless @schemaBlock.hideProjectmetadata}} +{{#if (or (not @schemaBlock.concealmentPageNavigator) (eq @schemaBlock.concealmentPageNavigator undefined)) }}

    {{this.localizedDisplayText}}

    -{{/unless}} +{{/if}} {{#if this.isEditableForm}} -

    {{this.localizedHelpText}}

    +
    + {{#each this.localizedHelpText as |line|}} +

    + {{#each line as |part|}} + {{#if (eq part.type 'link')}} + + {{part.content}} + + {{else}} + {{part.content}} + {{/if}} + {{/each}} +

    + {{/each}} +
    {{/if}} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/mapper/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/mapper/template.hbs index 9e9e2e9cd..3c47bbd32 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/mapper/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/mapper/template.hbs @@ -129,6 +129,13 @@ changeset=@changeset node=@node ) + ad-metadata-input=( + component + 'registries/schema-block-renderer/read-only/rdm/ad-metadata-input' + registrationResponses=@registrationResponses + changeset=@changeset + node=@node + ) array-input=( component 'registries/schema-block-renderer/read-only/rdm/array-input' diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.ts b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.ts new file mode 100644 index 000000000..8e3980ab5 --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.ts @@ -0,0 +1,79 @@ +import { tagName } from '@ember-decorators/component'; +import Component from '@ember/component'; +import { assert } from '@ember/debug'; + +import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; +import { inject as service } from '@ember/service'; +import { ChangesetDef } from 'ember-changeset/types'; +import Intl from 'ember-intl/services/intl'; +import { layout } from 'ember-osf-web/decorators/component'; +import NodeModel from 'ember-osf-web/models/node'; +import styles from './styles'; +import template from './template'; + +interface FileMetadataEntity { + comments?: any[]; + extra?: any[]; + value: any; +} + +interface FileMetadata { + path: string; + urlpath: string | null; + metadata: { + [key: string]: FileMetadataEntity, + }; +} + +interface FileEntry { + path: string; +} + +@layout(template, styles) +@tagName('') +export default class AdMetadataInput extends Component { + @service intl!: Intl; + + // Required param + changeset!: ChangesetDef; + node!: NodeModel; + + @alias('schemaBlock.registrationResponseKey') + valuePath!: string; + onInput!: () => void; + + didReceiveAttrs() { + assert( + 'Registries::SchemaBlockRenderer::Editable::Rdm::AdMetadataInput requires a changeset to render', + Boolean(this.changeset), + ); + assert( + 'Registries::SchemaBlockRenderer::Editable::Rdm::AdMetadataInput requires a node to render', + Boolean(this.node), + ); + assert( + 'Registries::SchemaBlockRenderer::Editable::Rdm::AdMetadataInput requires a valuePath to render', + Boolean(this.valuePath), + ); + } + + @computed('changeset', 'valuePath') + get adMetadatas(): FileMetadata[] { + if (!this.changeset) { + return []; + } + const value = this.changeset.get(this.valuePath); + if (!value) { + return []; + } + return JSON.parse(value) as FileMetadata[]; + } + + @computed('adMetadatas') + get fileEntries(): FileEntry[] { + return this.get('adMetadatas').map(metadata => ({ + path: metadata.path, + }) as FileEntry); + } +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/styles.scss new file mode 100644 index 000000000..f29e4bdb2 --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/styles.scss @@ -0,0 +1,49 @@ +.file-metadata-input-container { + width: 100%; + border: 1px solid #eee; + padding: 0.5em; +} + +.file-metadata-input-files { + border: 1px solid #eee; +} + +.file-metadata-input-files th { + border: 1px solid #eee; + background: #f5f5f5; + height: 35px; +} + +.file-metadata-input-files td { + border-top: 1px solid #eee; + height: 35px; +} + +.file-metadata-input-files .file-metadata-path { + max-width: 250px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-files .file-metadata-title { + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-files .file-metadata-manager { + max-width: 50px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-metadata-input-edit-button { + padding: 0 !important; +} + +.file-metadata-input-buttons { + margin-bottom: 4px; +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/template.hbs new file mode 100644 index 000000000..0bdf64fdc --- /dev/null +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/template.hbs @@ -0,0 +1,24 @@ + + {{#if this.fileEntries }} + + + + + + + + {{#each this.fileEntries as |fileEntry|}} + + + + {{/each}} + +
    + {{t 'metadata.file-metadata-input.columns.path'}} +
    + {{fileEntry.path}} +
    + {{else}} + + {{/if}} +
    \ No newline at end of file diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/styles.scss b/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/styles.scss index 24b104d74..fa7090685 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/styles.scss +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/styles.scss @@ -3,3 +3,19 @@ color: $color-text-gray-blue; } + +.HelpText { + composes: Element from '../styles'; + + // white-space: pre-wrap; + font-weight: 400; + margin-top: 0; +} + + +.HelpTextLine { + font-weight: normal !important; + margin-bottom: 0; + font-size: 14px; + margin-top: 17px; +} diff --git a/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/template.hbs b/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/template.hbs index 94bc882bb..58636f61b 100644 --- a/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/template.hbs +++ b/lib/osf-components/addon/components/registries/schema-block-renderer/section-heading/template.hbs @@ -4,6 +4,9 @@ ...attributes > {{this.localizedDisplayText}} +
    +

    {{this.schemaBlock.helpText}}

    +
    {{#if this.isEditableForm}} diff --git a/lib/osf-components/addon/components/validated-input/text/component.ts b/lib/osf-components/addon/components/validated-input/text/component.ts index 13cf6c92f..fcf96b7ef 100644 --- a/lib/osf-components/addon/components/validated-input/text/component.ts +++ b/lib/osf-components/addon/components/validated-input/text/component.ts @@ -1,9 +1,8 @@ +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; import DS, { AttributesFor } from 'ember-data'; - import { layout } from 'ember-osf-web/decorators/component'; import defaultTo from 'ember-osf-web/utils/default-to'; - -import { action } from '@ember/object'; import BaseValidatedComponent from '../base-component'; import template from './template'; @@ -11,12 +10,57 @@ import template from './template'; export default class ValidatedText extends BaseValidatedComponent { valuePath!: AttributesFor; + @service store!: DS.Store; + // Additional arguments password: boolean = defaultTo(this.password, false); onKeyUp?: () => void; // Action - onChange?: () => void; // Action title?: string = this.title; + getRetrievalTitle: string = defaultTo(this.getRetrievalTitle, ''); + getRetrievalDate: string = defaultTo(this.getRetrievalDate, ''); + getRetrievalVersion: string = defaultTo(this.getRetrievalVersion, ''); + + datetimeInitiated: Date = defaultTo(this.datetimeInitiated, new Date()); + datetimeUpdated: Date = defaultTo(this.datetimeUpdated, new Date()); + + getEdit: boolean = defaultTo(this.getEdit, false); + + didInsertElement() { + if (this.datetimeUpdated instanceof Date && !isNaN(this.datetimeUpdated.getTime()) + && this.datetimeInitiated instanceof Date + && !isNaN(this.datetimeInitiated.getTime())) { + const diffInMs = this.datetimeUpdated.getTime() - this.datetimeInitiated.getTime(); + const diffInMinutes = diffInMs / 1000 / 60; + + if ( + (this.getRetrievalTitle === 'auto_retrieval' || this.getRetrievalTitle === 'dual_retrieval') + && diffInMinutes <= 1 + ) { + this.set('value', this.title); + } + + if ( + (this.getRetrievalDate === 'auto_retrieval' || this.getRetrievalDate === 'dual_retrieval') + && diffInMinutes <= 1 + ) { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const date = String(now.getDate()).padStart(2, '0'); + + this.set('value', `${year}-${month}-${date}`); + } + } else { + // Invalid date values for datetimeInitiated or datetimeUpdated. + } + + this.set('getEdit', this.getEdit === true); + + if (this.getRetrievalVersion !== '') { + this.set('value', this.getRetrievalVersion); + } + } @action getTitle() { @@ -25,10 +69,17 @@ export default class ValidatedText extends BaseValidatedComp @action getDate() { - this.set( - 'value', - `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new - Date().getDate()).padStart(2, '0')}`, - ); + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const date = String(now.getDate()).padStart(2, '0'); + + this.set('value', `${year}-${month}-${date}`); + } + + @action + onChange(event: Event) { + const target = event.target as HTMLInputElement; + this.set('value', target.value); } } diff --git a/lib/osf-components/addon/components/validated-input/text/template.hbs b/lib/osf-components/addon/components/validated-input/text/template.hbs index a5f3c442c..3c47994b4 100644 --- a/lib/osf-components/addon/components/validated-input/text/template.hbs +++ b/lib/osf-components/addon/components/validated-input/text/template.hbs @@ -2,6 +2,9 @@ model=this.model changeset=this.changeset title=this.title + datetimeInitiated=this.datetimeInitiated + datetimeUpdated=this.datetimeUpdated + nodeId=this.nodeId errors=this.errors label=this.label valuePath=this.valuePath @@ -17,25 +20,25 @@ @class='form-control' @name={{@valuePath}} @keyUp={{@onKeyUp}} - @change={{@onChange}} - @disabled={{this.disabled}} + @change={{action this.onChange}} + @disabled={{this.getEdit}} /> - {{#if @autoTitle}} + {{#if (or (eq @getRetrievalTitle 'button_retrieval') (eq @getRetrievalTitle 'dual_retrieval'))}} - {{t 'registries.drafts.draft.form.auto_button_label'}} + {{t 'registries.drafts.draft.form.get_retrieval_label'}} {{/if}} - {{#if @autoDate}} + {{#if (or (eq @getRetrievalDate 'button_retrieval') (eq @getRetrievalDate 'dual_retrieval'))}} - {{t 'registries.drafts.draft.form.auto_button_label'}} + {{t 'registries.drafts.draft.form.get_retrieval_label'}} {{/if}} {{/validated-input/x-input-wrapper}} diff --git a/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/component.js b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/component.js new file mode 100644 index 000000000..804d31e86 --- /dev/null +++ b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/component.js @@ -0,0 +1,2 @@ +export { default } from + 'osf-components/components/registries/schema-block-renderer/editable/rdm/ad-metadata-input/component'; diff --git a/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.js b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.js new file mode 100644 index 000000000..91d59780a --- /dev/null +++ b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component.js @@ -0,0 +1,2 @@ +export { default } from + 'osf-components/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component'; diff --git a/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.js b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.js new file mode 100644 index 000000000..354b25160 --- /dev/null +++ b/lib/osf-components/app/components/registries/schema-block-renderer/editable/rdm/singleselect-pulldown-input/component.js @@ -0,0 +1,2 @@ +export { default } from + 'osf-components/components/registries/schema-block-renderer/editable/rdm/single-select-pulldown-input/component'; diff --git a/lib/osf-components/app/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.js b/lib/osf-components/app/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.js new file mode 100644 index 000000000..4bd11e191 --- /dev/null +++ b/lib/osf-components/app/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component.js @@ -0,0 +1,2 @@ +export { default } from + 'osf-components/components/registries/schema-block-renderer/read-only/rdm/ad-metadata-input/component'; diff --git a/lib/registries/addon/drafts/draft/-components/right-nav/component.ts b/lib/registries/addon/drafts/draft/-components/right-nav/component.ts new file mode 100644 index 000000000..022ef2313 --- /dev/null +++ b/lib/registries/addon/drafts/draft/-components/right-nav/component.ts @@ -0,0 +1,93 @@ +import { tagName } from '@ember-decorators/component'; +import Component from '@ember/component'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import DS from 'ember-data'; +import Intl from 'ember-intl/services/intl'; +import { layout } from 'ember-osf-web/decorators/component'; +import DraftRegistration from 'ember-osf-web/models/draft-registration'; +import Toast from 'ember-toastr/services/toast'; +import template from './template'; + +@tagName('') +@layout(template) +export default class RightNav extends Component { + @service store!: DS.Store; + draftRegistrations: DraftRegistration[] = []; + @service toast!: Toast; + + @service router!: any; + disableButtons: boolean = false; + @service intl!: Intl; + + constructor(...args: any[]) { + super(...args); + this.handleRouteChange(); + this.router.on('routeDidChange', this.handleRouteChange); + } + + willDestroy() { + super.willDestroy(); + this.router.off('routeDidChange', this.handleRouteChange); + } + + @action + async handleRouteChange() { + const currentUrl = window.location.href; + const urlParts = currentUrl.split('/'); + const lastPartWithQuery = urlParts[urlParts.length - 1]; + const metadataTitle = lastPartWithQuery.split('?')[0]; + const cleanedTitle = metadataTitle.replace(/^\d+-/, ''); + const title = decodeURIComponent(cleanedTitle.replace(/-/g, ' ')); + const allSchemas = await this.store.findAll('registration-schema'); + + const matchedSchema = allSchemas.find( + (schema: any) => schema.schema.pages.some( + (page: any) => page.title.trim().toLowerCase() === title.trim().toLowerCase() + && page.clipboardCopyPaste === false, + ), + ); + + if (!this.isDestroyed && !this.isDestroying) { + this.set('disableButtons', !!matchedSchema); + } + } + + @action + async pasteFromClipboard() { + try { + const clipboardText = await navigator.clipboard.readText(); + try { + const parsedJson = JSON.parse(clipboardText); + const structuredJson: {[key: string]: any } = {}; + Object.entries(parsedJson).forEach(([key, value]) => { + structuredJson[key] = { + extra: [], + value, + comments: [], + }; + }); + + const currentUrl = window.location.href; + const idRegex = /\/drafts\/([a-f0-9]{24})/; + const match = currentUrl.match(idRegex); + if (match && match[1]) { + try { + const draftId = match[1]; + const draftRegistration = await this.store.findRecord('draft-registration', draftId); + draftRegistration.set('registrationMetadata', structuredJson); + await draftRegistration.save(); + window.location.reload(); + this.toast.success(this.intl.t('registries.drafts.draft.form.clipboard_pasted')); + } catch (error) { + this.toast.success(this.intl.t('registries.drafts.draft.form.json_invalid'), error); + } + } + } catch (error) { + this.toast.success(this.intl.t('registries.drafts.draft.form.clipboard_unread'), error); + } + } catch (error) { + this.toast.error('Failed to read from clipboard: ', error); + } + } +} diff --git a/lib/registries/addon/drafts/draft/-components/right-nav/styles.scss b/lib/registries/addon/drafts/draft/-components/right-nav/styles.scss index e69de29bb..a9a447dbc 100644 --- a/lib/registries/addon/drafts/draft/-components/right-nav/styles.scss +++ b/lib/registries/addon/drafts/draft/-components/right-nav/styles.scss @@ -0,0 +1,11 @@ +.Label { + float: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + word-wrap: break-word; + + &:hover { + overflow: visible; + } +} diff --git a/lib/registries/addon/drafts/draft/-components/right-nav/template.hbs b/lib/registries/addon/drafts/draft/-components/right-nav/template.hbs index 0fc70271c..4a126874e 100644 --- a/lib/registries/addon/drafts/draft/-components/right-nav/template.hbs +++ b/lib/registries/addon/drafts/draft/-components/right-nav/template.hbs @@ -60,4 +60,15 @@ - \ No newline at end of file + + + + {{t 'registries.drafts.draft.form.from_clipboard_paste'}} + \ No newline at end of file diff --git a/lib/registries/addon/drafts/draft/template.hbs b/lib/registries/addon/drafts/draft/template.hbs index d042bfd78..3d70ccf22 100644 --- a/lib/registries/addon/drafts/draft/template.hbs +++ b/lib/registries/addon/drafts/draft/template.hbs @@ -39,7 +39,7 @@ {{#each draftManager.pageManagers as |pageManager index|}} {{#let (get pageManager.schemaBlockGroups 0) as |group|}} - {{#unless group.labelBlock.hideProjectmetadata}} + {{#unless group.labelBlock.concealmentPageNavigator}}