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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [25.12.0] - 2025-06-13
### Added
- Google File Picker workflow
- Misc. improvements

## [25.11.0] - 2025-06-11
### Added
- Manual GUID and DOI assignment during Preprint and Registration Creation

## [25.10.0] - 2025-05-13
### Added
- Re-enable view and download counts for preprints
Expand Down
6 changes: 6 additions & 0 deletions app/config/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ declare const config: {
doiUrlPrefix: string;
dataciteTrackerRepoId: string;
dataCiteTrackerUrl: string;
googleFilePicker: {
GOOGLE_FILE_PICKER_SCOPES: string;
GOOGLE_FILE_PICKER_CLIENT_ID: string;
GOOGLE_FILE_PICKER_API_KEY: string;
GOOGLE_FILE_PICKER_APP_ID: number;
}
};
social: {
twitter: {
Expand Down
1 change: 1 addition & 0 deletions app/guid-node/files/provider/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
>
<div local-class='FileBrowser'>
<FileBrowser
@configuredStorageAddon={{this.model.configuredStorageAddon}}
@manager={{manager}}
@selectable={{not this.model.providerTask.value.currentUser.viewOnlyToken}}
@enableUpload={{true}}
Expand Down
3 changes: 1 addition & 2 deletions app/models/authorized-account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Model, { attr } from '@ember-data/model';
import Model, { attr} from '@ember-data/model';
import { OperationKwargs } from 'ember-osf-web/models/addon-operation-invocation';

export enum ConnectedCapabilities {
Expand Down Expand Up @@ -36,7 +36,6 @@ export default class AuthorizedAccountModel extends Model {
return;
}


async getItemInfo(this: AuthorizedAccountModel, _itemId: string) : Promise<any> {
// To be implemented in child classes
return;
Expand Down
7 changes: 5 additions & 2 deletions app/models/authorized-storage-account.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { AsyncBelongsTo, belongsTo } from '@ember-data/model';
import { AsyncBelongsTo, attr, belongsTo } from '@ember-data/model';
import { waitFor } from '@ember/test-waiters';
import { task } from 'ember-concurrency';
import { ConnectedStorageOperationNames, OperationKwargs } from 'ember-osf-web/models/addon-operation-invocation';
import ExternalStorageServiceModel from 'ember-osf-web/models/external-storage-service';

import ExternalStorageServiceModel from './external-storage-service';
import AuthorizedAccountModel from './authorized-account';
import UserReferenceModel from './user-reference';

export default class AuthorizedStorageAccountModel extends AuthorizedAccountModel {
@attr('fixstring') serializeOauthToken!: string;
@attr('fixstring') oauthToken!: string;

@belongsTo('user-reference', { inverse: 'authorizedStorageAccounts' })
readonly accountOwner!: AsyncBelongsTo<UserReferenceModel> & UserReferenceModel;

Expand Down
2 changes: 1 addition & 1 deletion app/models/index-card-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface SearchFilter {
filterType?: string;
}

export const ShareMoreThanTenThousand = 'https://share.osf.io/vocab/2023/trove/ten-thousands-and-more';
export const ShareMoreThanTenThousand = 'trove:ten-thousands-and-more';

export default class IndexCardSearchModel extends Model {
@attr('string') cardSearchText!: string;
Expand Down
2 changes: 2 additions & 0 deletions app/models/preprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export default class PreprintModel extends AbstractNodeModel {
@attr('string') preregLinkInfo!: PreprintPreregLinkInfoEnum;
@attr('number') version!: number;
@attr('boolean') isLatestVersion!: boolean;
@attr('string') manualDoi!: string;
@attr('string') manualGuid!: string;

@belongsTo('node', { inverse: 'preprints' })
node!: AsyncBelongsTo<NodeModel> & NodeModel;
Expand Down
2 changes: 2 additions & 0 deletions app/models/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ export default class RegistrationModel extends NodeModel.extend(Validations) {
@attr('boolean') hasAnalyticCode!: boolean;
@attr('boolean') hasPapers!: boolean;
@attr('boolean') hasSupplements!: boolean;
@attr('string') manualDoi!: string;
@attr('string') manualGuid!: string;

// Write-only attributes
@attr('array') includedNodeIds?: string[];
Expand Down
2 changes: 1 addition & 1 deletion app/models/search-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export default class SearchResultModel extends Model {
}

get isWithdrawn() {
return this.resourceMetadata.dateWithdrawn || this.resourceMetadata['https://osf.io/vocab/2022/withdrawal'];
return this.resourceMetadata.dateWithdrawn || this.resourceMetadata['osf:withdrawal'];
}

get configuredAddonNames() {
Expand Down
1 change: 1 addition & 0 deletions app/packages/addons-service/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ export default class Provider {
accountOwner: this.userReference,
});
await newAccount.save();
newAccount.initiateOauth = null;
return newAccount;
}

Expand Down
21 changes: 20 additions & 1 deletion app/preprints/-components/submit/title-and-abstract/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import Component from '@glimmer/component';
import PreprintStateMachine from 'ember-osf-web/preprints/-components/submit/preprint-state-machine/component';
import { action } from '@ember/object';
import { ValidationObject } from 'ember-changeset-validations';
import { validatePresence, validateLength } from 'ember-changeset-validations/validators';
import { validatePresence, validateLength, validateFormat } from 'ember-changeset-validations/validators';
import buildChangeset from 'ember-osf-web/utils/build-changeset';
import { inject as service } from '@ember/service';
import Intl from 'ember-intl/services/intl';
import { DOIRegex } from 'ember-osf-web/utils/doi';

/**
* The TitleAndAbstract Args
Expand All @@ -17,6 +18,8 @@ interface TitleAndAbstractArgs {
interface TitleAndAbstractForm {
title: string;
description: string;
manualDoi: string;
manualGuid: string;
}

/**
Expand Down Expand Up @@ -45,6 +48,22 @@ export default class TitleAndAbstract extends Component<TitleAndAbstractArgs>{
},
}),
],
manualDoi: validateFormat({
allowBlank: true,
allowNone: true,
ignoreBlank: true,
regex: DOIRegex,
type: 'invalid_doi',
}),
manualGuid: validateLength({
allowBlank: true,
min:5,
type: 'greaterThanOrEqualTo',
translationArgs: {
description: this.intl.t('preprints.submit.step-title.guid'),
gte: '5 characters',
},
}),
};

titleAndAbstractFormChangeset = buildChangeset(this.args.manager.preprint, this.titleAndAbstractFormValidation);
Expand Down
36 changes: 36 additions & 0 deletions app/preprints/-components/submit/title-and-abstract/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,42 @@
@onKeyUp={{this.validate}}
/>
{{/let}}
{{#if (and (feature-flag 'manual_doi_and_guid') (not @manager.isEditFlow))}}
{{#let (unique-id 'manualDoi') as |manualDoiField|}}
<label for={{manualDoiField}}
data-test-manual-doi-label
>
{{t 'preprints.submit.step-title.doi'}}
<span local-class='required'>*</span>
</label>
<form.text
data-test-manual-doi-input
@valuePath={{'manualDoi'}}
@isRequired={{false}}
{{on 'change' this.validate}}
local-class='input-container'
@uniqueID={{manualDoiField}}
@onKeyUp={{this.validate}}
/>
{{/let}}
{{#let (unique-id 'manualGuid') as |manualGuidField|}}
<label for={{manualGuidField}}
data-test-manudal-guid-label
>
{{t 'preprints.submit.step-title.guid'}}
<span local-class='required'>*</span>
</label>
<form.text
data-test-manual-guid-input
@valuePath={{'manualGuid'}}
@isRequired={{false}}
{{on 'change' this.validate}}
local-class='input-container'
@uniqueID={{manualGuidField}}
@onKeyUp={{this.validate}}
/>
{{/let}}
{{/if}}
</FormControls>
</div>
</div>
14 changes: 14 additions & 0 deletions config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ const {
SHARE_SEARCH_URL: shareSearchUrl = 'http://localhost:8003/api/v2/search/creativeworks/_search',
SOURCEMAPS_ENABLED: sourcemapsEnabled = true,
SHOW_DEV_BANNER = false,

GOOGLE_FILE_PICKER_SCOPES,
/* eslint-disable-next-line max-len */
GOOGLE_FILE_PICKER_CLIENT_ID,
GOOGLE_FILE_PICKER_API_KEY,
GOOGLE_FILE_PICKER_APP_ID,

} = { ...process.env, ...localConfig };

module.exports = function(environment) {
Expand Down Expand Up @@ -224,6 +231,12 @@ module.exports = function(environment) {
doiUrlPrefix: 'https://doi.org/',
dataciteTrackerRepoId,
dataCiteTrackerUrl,
googleFilePicker: {
GOOGLE_FILE_PICKER_SCOPES,
GOOGLE_FILE_PICKER_CLIENT_ID,
GOOGLE_FILE_PICKER_API_KEY,
GOOGLE_FILE_PICKER_APP_ID,
},
},
social: {
twitter: {
Expand Down Expand Up @@ -316,6 +329,7 @@ module.exports = function(environment) {
},
storageI18n: 'storage_i18n',
gravyWaffle: 'gravy_waffle',
manualDoiAndGuid: 'manual_doi_and_guid',
enableInactiveSchemas: 'enable_inactive_schemas',
verifyEmailModals: 'ember_verify_email_modals',
ABTesting: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default class ActivityLogComponent extends Component {
public loadEmbeds = {
embed:
[
'group', 'linked_node', 'linked_registration', 'original_node',
'linked_node', 'linked_registration', 'original_node',
'template_node', 'user',
],
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { action } from '@ember/object';
import { waitFor } from '@ember/test-waiters';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { TaskInstance } from 'ember-concurrency';
import { task, TaskInstance } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';


import { Item, ItemType } from 'ember-osf-web/models/addon-operation-invocation';
import AuthorizedAccountModel from 'ember-osf-web/models/authorized-account';
Expand All @@ -12,6 +15,7 @@ import ConfiguredAddonModel from 'ember-osf-web/models/configured-addon';
import ConfiguredCitationAddonModel from 'ember-osf-web/models/configured-citation-addon';
import ConfiguredComputingAddonModel from 'ember-osf-web/models/configured-computing-addon';
import ConfiguredStorageAddonModel from 'ember-osf-web/models/configured-storage-addon';
import ExternalStorageServiceModel from 'ember-osf-web/models/external-storage-service';


interface Args {
Expand All @@ -25,6 +29,8 @@ export default class ConfiguredAddonEdit extends Component<Args> {
@tracked selectedFolder = this.args.configuredAddon?.rootFolder;
@tracked selectedFolderDisplayName = this.args.configuredAddon?.rootFolderName;
@tracked currentItems: Item[] = [];
@tracked isWBGoogleDrive = false;
@tracked accountId!: string;

originalName = this.displayName;
originalRootFolder = this.selectedFolder;
Expand All @@ -34,6 +40,7 @@ export default class ConfiguredAddonEdit extends Component<Args> {
super(owner, args);
if (this.args.configuredAddon) {
if (this.args.configuredAddon instanceof ConfiguredStorageAddonModel) {
taskFor(this.loadExternalStorageService).perform();
this.defaultKwargs['itemType'] = ItemType.Folder;
}
if (this.args.configuredAddon instanceof ConfiguredCitationAddonModel) {
Expand All @@ -42,6 +49,7 @@ export default class ConfiguredAddonEdit extends Component<Args> {
}
if (this.args.authorizedAccount) {
if (this.args.authorizedAccount instanceof AuthorizedStorageAccountModel) {
taskFor(this.loadExternalStorageService).perform();
this.defaultKwargs['itemType'] = ItemType.Folder;
}
if (this.args.authorizedAccount instanceof AuthorizedCitationAccountModel) {
Expand All @@ -50,6 +58,28 @@ export default class ConfiguredAddonEdit extends Component<Args> {
}
}

/**
* This is called only to authorize because the current implementation will throw an
* error because the "root folder" is not yet set.
*/
@task
@waitFor
async loadExternalStorageService() {
let external!: ExternalStorageServiceModel;
if (this.args.configuredAddon && this.args.configuredAddon instanceof ConfiguredStorageAddonModel) {
const baseAccount = await this.args.configuredAddon.baseAccount;
this.accountId = baseAccount?.id;
external = await this.args.configuredAddon.externalStorageService;
}
if (this.args.authorizedAccount && this.args.authorizedAccount instanceof AuthorizedStorageAccountModel) {
external = await this.args.authorizedAccount.externalStorageService;

this.accountId = this.args.authorizedAccount.id;
}

this.isWBGoogleDrive = external?.wbKey === 'googledrive';
}

get requiresRootFolder() {
return !(
this.args.authorizedAccount instanceof AuthorizedComputingAccountModel
Expand All @@ -58,6 +88,14 @@ export default class ConfiguredAddonEdit extends Component<Args> {
);
}

get isGoogleDrive(): boolean {
return this.isWBGoogleDrive;
}

get displayFileManager(): boolean {
return this.requiresRootFolder && !this.isGoogleDrive;
}

get invalidDisplayName() {
return !this.displayName || this.displayName?.trim().length === 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,8 @@
.item-name {
white-space: normal;
}

.picker-style {
white-space: pre-wrap;

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</span>
{{/if}}
</div>
{{#if this.requiresRootFolder }}
{{#if this.displayFileManager}}
<div local-class='input-wrapper'>
<b>
{{t 'addons.configure.selected-folder'}}
Expand Down Expand Up @@ -150,6 +150,13 @@
</tbody>
</table>
</AddonsService::FileManager>
{{else}}
<GoogleFilePickerWidget
@selectedFolderName={{this.selectedFolderDisplayName}}
@selectFolder={{action this.selectFolder}}
@isFolderPicker={{true}}
@accountId={{this.accountId}}
></GoogleFilePickerWidget>
{{/if}}
<div local-class='footer-buttons-wrapper'>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,8 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
@waitFor
async createAuthorizedAccount(arg: AccountCreationArgs) {
if (this.selectedProvider) {
const newAccount = await taskFor(this.selectedProvider.createAuthorizedAccount)
return await taskFor(this.selectedProvider.createAuthorizedAccount)
.perform(arg);
return newAccount;
}
return undefined;
}
Expand Down
Loading