+
+
{{yield to='header'}}
{{yield to='body'}}
diff --git a/app/guid-file/-components/file-header/styles.scss b/app/guid-file/-components/file-header/styles.scss
new file mode 100644
index 00000000000..a4ecbeebb8d
--- /dev/null
+++ b/app/guid-file/-components/file-header/styles.scss
@@ -0,0 +1,64 @@
+// stylelint-disable max-nesting-depth, selector-max-compound-selectors
+
+.file-header-container {
+ width: 100%;
+
+ .flex-container-row {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 0 20px 20px;
+
+ h2 {
+ height: 40px;
+ width: 70%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .return-container {
+ width: 30%;
+ height: 70px;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ }
+ }
+
+ .project-link-header {
+ padding-bottom: 5px;
+
+ .project-link {
+ margin: 20px;
+ }
+ }
+
+ &.mobile {
+ padding: 0;
+
+ .flex-container-row {
+ padding: 0;
+ flex-direction: column;
+
+ h2,
+ .return-container {
+ width: 100%;
+ height: fit-content;
+ justify-content: flex-start;
+ }
+
+ h2 {
+ margin-top: 0;
+ }
+ }
+
+ .project-link-header {
+ .project-link {
+ margin: 0;
+ }
+ }
+ }
+}
diff --git a/app/guid-file/-components/file-header/template.hbs b/app/guid-file/-components/file-header/template.hbs
new file mode 100644
index 00000000000..758c2de4ba1
--- /dev/null
+++ b/app/guid-file/-components/file-header/template.hbs
@@ -0,0 +1,40 @@
+
+
+
+ {{@model.fileModel.target.title}}
+
+
+
+
+ {{@model.displayName}}
+ {{#if @viewedVersion}}
+ ({{t 'general.version'}}: {{@viewedVersion}})
+ {{/if}}
+
+
+ {{#if @displayFileActions}}
+
+ {{else}}
+
+ {{ t 'file-detail.metadata.return-to-file' fileName=@model.displayName}}
+
+ {{/if}}
+
+
+
\ No newline at end of file
diff --git a/app/guid-file/controller.ts b/app/guid-file/index/controller.ts
similarity index 95%
rename from app/guid-file/controller.ts
rename to app/guid-file/index/controller.ts
index 94bdbef9952..ea6af99cba0 100644
--- a/app/guid-file/controller.ts
+++ b/app/guid-file/index/controller.ts
@@ -40,8 +40,8 @@ export default class GuidFile extends Controller {
@action
toggleRevisions() {
- if (!this.model.waterButlerRevisions) {
- taskFor(this.model.getRevisions).perform();
+ if (!this.model.file.waterButlerRevisions) {
+ taskFor(this.model.file.getRevisions).perform();
}
if (this.isMobile) {
this.revisionsOpened = true;
@@ -113,6 +113,6 @@ export default class GuidFile extends Controller {
@action
onDelete() {
- this.router.transitionTo('guid-node.files', this.model.fileModel.target.get('id'));
+ this.router.transitionTo('guid-node.files', this.model.file.fileModel.target.get('id'));
}
}
diff --git a/app/guid-file/index/route.ts b/app/guid-file/index/route.ts
new file mode 100644
index 00000000000..139f21b0a86
--- /dev/null
+++ b/app/guid-file/index/route.ts
@@ -0,0 +1,38 @@
+import Store from '@ember-data/store';
+import Route from '@ember/routing/route';
+import RouterService from '@ember/routing/router-service';
+import { inject as service } from '@ember/service';
+import CedarMetadataRecordModel from 'ember-osf-web/models/cedar-metadata-record';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+
+
+export default class MetadataDetailRoute extends Route {
+ @service store!: Store;
+ @service router!: RouterService;
+
+ async model() {
+ const file = this.modelFor('guid-file');
+ const defaultIndex = 0;
+ const cedarMetadataRecords = await file.fileModel.queryHasMany('cedarMetadataRecords', {
+ 'page[size]': 20,
+ });
+
+ for(const cedarMetadataRecord of cedarMetadataRecords) {
+ const template = await cedarMetadataRecord.template as CedarMetadataTemplateModel;
+ template.recordCreated = true;
+ cedarMetadataRecord.templateName = template.schemaName;
+ }
+
+ cedarMetadataRecords.sort(
+ (a: CedarMetadataRecordModel, b: CedarMetadataRecordModel) =>
+ a.templateName > b.templateName ? 1 : -1,
+ );
+
+
+ return {
+ file,
+ cedarMetadataRecords,
+ defaultIndex,
+ };
+ }
+}
diff --git a/app/guid-file/index/styles.scss b/app/guid-file/index/styles.scss
new file mode 100644
index 00000000000..d0853962b09
--- /dev/null
+++ b/app/guid-file/index/styles.scss
@@ -0,0 +1,100 @@
+// stylelint-disable max-nesting-depth, selector-max-compound-selectors
+
+.flex-container-row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 0 20px 20px;
+
+ h2 {
+ height: 40px;
+ max-width: 70vw;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+}
+
+.project-link-header {
+ padding-bottom: 5px;
+
+ .project-link {
+ margin: 20px;
+ }
+}
+
+
+.file-header-container {
+ margin: 30px;
+ padding-top: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+ min-width: 330px;
+
+ &.mobile {
+ margin-bottom: 10px;
+ margin-top: 0;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 0;
+ }
+}
+
+.file-renderer {
+ height: 90vh;
+ margin-bottom: 15px;
+ padding: 0 20px 20px;
+}
+
+.slide-buttons {
+ background-color: $color-bg-white;
+ border: 1px transparent;
+ color: $color-link-dark;
+ margin: 0;
+
+ &.active {
+ background-color: $color-bg-gray-light;
+ }
+}
+
+.file-detail-revisions {
+ max-height: 100vh;
+ overflow-y: auto;
+}
+
+.file-detail-right-section-heading {
+ margin-left: 20px;
+}
+
+.file-detail-revision-list {
+ list-style-position: inside;
+ padding-inline: 20px;
+}
+
+.right-container {
+ display: inline-flex;
+ flex-direction: column;
+ height: 95%;
+ margin: 0 20px 20px;
+
+ &.mobile {
+ width: 90vw;
+ }
+
+ h2 {
+ font-size: 31.5px;
+ font-weight: 300;
+ line-height: 1.1;
+ margin-bottom: 20px;
+ }
+}
+
+.metadata-tab-container {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
diff --git a/app/guid-file/index/template.hbs b/app/guid-file/index/template.hbs
new file mode 100644
index 00000000000..c120290395c
--- /dev/null
+++ b/app/guid-file/index/template.hbs
@@ -0,0 +1,120 @@
+
+ <:header>
+
+
+
+
+ <:body>
+
+
+
+
+ <:right>
+ {{#if this.revisionsOpened}}
+
+ {{t 'general.revisions'}}
+
+
+ {{#if this.model.file.getRevisions.isRunning}}
+
+ {{else}}
+ {{#each this.model.file.waterButlerRevisions as |version|}}
+
+
+ {{else}}
+ {{t 'file-detail.no-revisions'}}
+ {{/each}}
+ {{/if}}
+
+
+ {{/if}}
+ {{#if this.tagsOpened}}
+
+
{{t 'general.tags'}}
+
+
+ {{/if}}
+ {{#if this.metadataOpened}}
+
+
+
+
+ {{/if}}
+
+ <:rightButtons>
+ {{#if this.media.isMobile}}
+
+
+
+ {{/if}}
+
+
+
+ {{#if this.model.file.shouldShowRevisions}}
+
+
+
+ {{/if}}
+ {{#if this.model.file.shouldShowTags}}
+
+
+
+ {{/if}}
+
+
diff --git a/app/guid-file/metadata/add/controller.ts b/app/guid-file/metadata/add/controller.ts
new file mode 100644
index 00000000000..c15d2dcc93b
--- /dev/null
+++ b/app/guid-file/metadata/add/controller.ts
@@ -0,0 +1,42 @@
+import Controller from '@ember/controller';
+import { inject as service } from '@ember/service';
+import Media from 'ember-responsive';
+import config from 'ember-osf-web/config/environment';
+import { action } from '@ember/object';
+import { tracked } from '@glimmer/tracking';
+import RouterService from '@ember/routing/router-service';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+import Intl from 'ember-intl/services/intl';
+
+export default class GuidFileMetadataAdd extends Controller {
+ @service media!: Media;
+ @service router!: RouterService;
+ @service intl!: Intl;
+
+ supportEmail = config.support.supportEmail;
+
+ @tracked displaySelectionOptions = true;
+ @tracked selectedTemplate?: CedarMetadataTemplateModel;
+
+ @action
+ selectTemplate(cedarMetadataTemplate: CedarMetadataTemplateModel): void {
+ this.displaySelectionOptions = false;
+ this.selectedTemplate = cedarMetadataTemplate;
+ }
+
+ @action
+ closeCedarEditor(): void {
+ this.displaySelectionOptions = true;
+ this.selectedTemplate = undefined;
+ }
+
+ get tabTitle(): string {
+ const translation = this.displaySelectionOptions ? 'metadata.add-flow.tab-title-select' :
+ 'metadata.add-flow.tab-title-add';
+ return this.intl.t(translation);
+ }
+
+ get isMobile() {
+ return this.media.isMobile;
+ }
+}
diff --git a/app/guid-file/metadata/add/route.ts b/app/guid-file/metadata/add/route.ts
new file mode 100644
index 00000000000..fca09225221
--- /dev/null
+++ b/app/guid-file/metadata/add/route.ts
@@ -0,0 +1,36 @@
+import Store from '@ember-data/store';
+import Route from '@ember/routing/route';
+import { inject as service } from '@ember/service';
+import GuidMetadataAdd from 'ember-osf-web/guid-node/metadata/add/controller';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+
+
+export default class GuidMetadataAddRoute extends Route {
+ @service store!: Store;
+
+ async model() {
+ const file = this.modelFor('guid-file');
+ const templates = await this.store.query('cedar-metadata-template', {
+ adapterOptions: { sort: 'schema_name' },
+ });
+
+ const cedarMetadataRecords = await file.fileModel.queryHasMany('cedarMetadataRecords', {
+ 'page[size]': 20,
+ });
+
+ for(const cedarMetadataRecord of cedarMetadataRecords) {
+ const template = await cedarMetadataRecord.template as CedarMetadataTemplateModel;
+ template.recordCreated = true;
+ cedarMetadataRecord.templateName = template.schemaName;
+ }
+
+ return {
+ target: file,
+ templates,
+ };
+ }
+
+ deactivate() {
+ (this.controller as GuidMetadataAdd).displaySelectionOptions = true;
+ }
+}
diff --git a/app/guid-file/metadata/add/styles.scss b/app/guid-file/metadata/add/styles.scss
new file mode 100644
index 00000000000..abdf1e8816a
--- /dev/null
+++ b/app/guid-file/metadata/add/styles.scss
@@ -0,0 +1,57 @@
+// stylelint-disable max-nesting-depth, selector-max-compound-selectors
+
+.metadata-add-container {
+ margin: 30px;
+ padding-top: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+ min-width: 330px;
+
+ .header-container {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ margin-bottom: 30px;
+
+ .header,
+ .explanation {
+ width: 100%;
+ margin-bottom: 30px;
+ }
+
+ .available-templates {
+ width: 100%;
+ font-weight: bold;
+ }
+ }
+
+ .template-container {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ }
+
+ &.mobile {
+ margin-top: 0;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 0;
+
+ .header-container {
+ flex-direction: column;
+ align-items: flex-start;
+ margin-bottom: 10px;
+
+ .header {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/app/guid-file/metadata/add/template.hbs b/app/guid-file/metadata/add/template.hbs
new file mode 100644
index 00000000000..d2cc1547643
--- /dev/null
+++ b/app/guid-file/metadata/add/template.hbs
@@ -0,0 +1,23 @@
+{{page-title this.tabTitle}}
+
+
+ {{#if this.displaySelectionOptions}}
+
+ {{else}}
+
+ {{/if}}
+
+
diff --git a/app/guid-file/route.ts b/app/guid-file/route.ts
index a25f7e95b35..89056750431 100644
--- a/app/guid-file/route.ts
+++ b/app/guid-file/route.ts
@@ -66,6 +66,7 @@ export default class GuidFile extends Route {
const { guid } = params;
try {
const file = await this.store.findRecord('file', guid, {include: 'target'});
+
this.metadata = await this.store.findRecord('custom-file-metadata-record', guid);
const target = await file.target as unknown as RegistrationModel;
diff --git a/app/guid-file/styles.scss b/app/guid-file/styles.scss
deleted file mode 100644
index 52797c68f49..00000000000
--- a/app/guid-file/styles.scss
+++ /dev/null
@@ -1,186 +0,0 @@
-.main-column {
- display: flex;
- flex-direction: column;
-}
-
-.flex-container-row {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- padding: 0 20px 20px;
-}
-
-.flex-container-row > h2 {
- height: 40px;
- max-width: 70vw;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.project-link-header {
- padding-bottom: 5px;
-}
-
-.project-link {
- margin: 20px;
-}
-
-.file-renderer {
- height: 90vh;
- margin-bottom: 15px;
- padding: 0 20px 20px;
-}
-
-.placeholder {
- color: #555;
-}
-
-.slide-buttons {
- background-color: $color-bg-white;
- border: 0;
- color: $color-link-dark;
- margin: 20px 20px 0;
-
- @media (max-width: 767px) {
- margin: 0;
- }
-
- &.active {
- @media (max-width: 767px) {
- background-color: $color-bg-white;
- color: $color-bg-black;
- }
- background-color: $color-bg-gray-light;
- }
-}
-
-.file-detail-revisions {
- max-height: 100vh;
- overflow-y: auto;
-}
-
-.file-detail-right-section-heading {
- margin-left: 20px;
-}
-
-.file-detail-revision-list {
- list-style-position: inside;
- padding-inline: 20px;
-}
-
-.file-detail-no-revisions {
- padding: 20px;
- text-align: center;
-}
-
-.right-container {
- display: inline-flex;
- flex-direction: column;
- height: 95%;
- margin: 0 20px 20px;
-
- &.mobile {
- width: 90vw;
- }
-
- dt {
- font-size: 17px;
- font-weight: 600;
- }
-
- dt,
- dd {
- background-color: #fff;
- color: #000;
- margin-bottom: 14px;
- }
-
- h2 {
- font-size: 31.5px;
- font-weight: 300;
- line-height: 1.1;
- margin-bottom: 20px;
- }
-
- dl {
- margin-bottom: 0;
- }
-
- h3 {
- font-size: 17px;
- font-weight: 600;
- margin-top: 10px;
- }
-}
-
-.metadata-heading {
- margin-bottom: 0;
-}
-
-.node-type-heading {
- border-top: 2px solid #ddd;
- border-top: 2px solid rgb(221, 221, 221);
- padding-top: 30px;
-}
-
-.metadata-title-edit-download {
- align-items: baseline;
- display: inline-flex;
- flex-direction: row;
- justify-content: space-between;
- white-space: nowrap;
- width: 100%;
-
- svg {
- height: 1.5em;
- }
-}
-
-.edit-download-buttons {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- margin-right: 1vw;
- grid-gap: 2vw;
-
- a,
- button {
- padding: 0.7vw 1.1vw;
- }
-
- button:active,
- button:focus,
- button:hover,
- a:active,
- a:focus,
- a:hover {
- background: #efefef;
- }
-}
-
-.metadata-form-and-buttons {
- display: flex;
- flex-direction: column;
- grid-gap: 20px;
- height: 100%;
- justify-content: flex-start;
-}
-
-.edit-metadata-form {
- display: inline-flex;
- flex-direction: column;
- max-width: 100%;
-}
-
-.edit-metadata-save-cancel-buttons {
- display: inline-flex;
- flex-direction: row;
- font-size: 14px;
- grid-gap: 1vw;
- justify-content: flex-end;
-}
-
-.affiliated-institutions {
- margin-top: 14px;
-}
diff --git a/app/guid-file/template.hbs b/app/guid-file/template.hbs
index f41e71b18c0..5ba51a8c98a 100644
--- a/app/guid-file/template.hbs
+++ b/app/guid-file/template.hbs
@@ -1,380 +1,2 @@
-
- <:header>
-
-
- {{this.model.fileModel.target.title}}
-
-
-
-
- {{this.model.displayName}}
- {{#if this.viewedVersion}}
- ({{t 'general.version'}}: {{this.viewedVersion}})
- {{/if}}
-
-
-
-
- <:body>
-
-
-
-
- <:right>
- {{#if this.revisionsOpened}}
-
- {{t 'general.revisions'}}
-
-
- {{#if this.model.getRevisions.isRunning}}
-
- {{else}}
- {{#each this.model.waterButlerRevisions as |version|}}
-
-
- {{else}}
- {{t 'file-detail.no-revisions'}}
- {{/each}}
- {{/if}}
-
-
- {{/if}}
- {{#if this.tagsOpened}}
-
-
{{t 'general.tags'}}
-
-
- {{/if}}
- {{#if this.metadataOpened}}
-
-
-
-
- {{t 'file-detail.file-metadata'}}
-
-
- {{#unless manager.inEditMode}}
- {{#if manager.userCanEdit}}
-
-
-
- {{/if}}
- {{#unless manager.isAnonymous}}
-
-
-
- {{/unless}}
- {{/unless}}
-
-
- {{#if manager.isGatheringData}}
-
- {{else}}
- {{#if manager.inEditMode}}
-
-
-
-
-
-
- {{option}}
-
-
- {{#if option.name}}
- {{option.name}}
- {{else}}
-
- {{t 'file-detail.choose-language'}}
-
- {{/if}}
-
-
-
-
-
- {{t 'general.cancel'}}
-
-
- {{t 'general.save'}}
-
-
-
- {{else}}
- {{#if (or
- manager.metadataRecord.title
- manager.metadataRecord.description
- manager.metadataRecord.resourceTypeGeneral
- manager.languageFromCode
- )}}
-
- {{#if manager.metadataRecord.title}}
- {{t 'file-detail.title'}}
- {{manager.metadataRecord.title}}
- {{/if}}
- {{#if manager.metadataRecord.description}}
- {{t 'file-detail.description'}}
-
-
- {{manager.metadataRecord.description}}
-
-
- {{/if}}
- {{#if manager.metadataRecord.resourceTypeGeneral}}
-
- {{t 'file-detail.resource-type-general'}}
-
-
-
-
-
- {{manager.metadataRecord.resourceTypeGeneral}}
- {{/if}}
- {{#if manager.languageFromCode}}
- {{t 'file-detail.language'}}
- {{manager.languageFromCode}}
- {{/if}}
-
- {{else}}
- {{#if manager.userCanEdit}}
- {{t 'file-detail.enter-metadata'}}
- {{/if}}
- {{/if}}
- {{t (concat 'file-detail.metadata-' manager.nodeWord)}}
- {{#unless manager.isAnonymous}}
-
- {{#each manager.targetMetadata.funders as |funder|}}
-
- {{#if funder.funder_name}}
- {{t 'file-detail.funder'}}
-
- {{funder.funder_name}}
-
- {{/if}}
- {{#if funder.award_title}}
- {{t 'file-detail.award-title'}}
-
- {{funder.award_title}}
-
- {{/if}}
- {{#if funder.award_uri}}
- {{t 'file-detail.award-uri'}}
-
- {{funder.award_uri}}
-
- {{/if}}
- {{#if funder.award_number}}
- {{t 'file-detail.award-number'}}
-
- {{funder.award_number}}
-
- {{/if}}
-
- {{/each}}
-
- {{/unless}}
-
- {{t 'file-detail.title'}}
- {{manager.target.title}}
- {{#if manager.target.description}}
- {{t 'file-detail.description'}}
-
-
- {{manager.target.description}}
-
-
- {{/if}}
- {{#if (and manager.targetInstitutions (not manager.isAnonymous))}}
- {{t 'file-detail.institutions'}}
-
- {{#each manager.targetInstitutions as |institution|}}
-
{{institution.name}}
- {{/each}}
-
- {{/if}}
- {{#if manager.targetLicense.name}}
- {{t 'file-detail.license'}}
- {{manager.targetLicense.name}}
- {{/if}}
- {{#if manager.targetMetadata.resourceTypeGeneral}}
- {{t 'file-detail.resource-type-general'}}
- {{manager.targetMetadata.resourceTypeGeneral}}
- {{/if}}
- {{#if manager.targetLanguageFromCode}}
- {{t 'file-detail.language'}}
- {{manager.targetLanguageFromCode}}
- {{/if}}
- {{t 'file-detail.creation-date'}}
-
- {{moment-format manager.target.dateCreated 'MMMM D, YYYY'}}
-
- {{t 'file-detail.modification-date'}}
-
- {{moment-format manager.target.dateModified 'MMMM D, YYYY'}}
-
- {{#if @manager.node.dateRegistered}}
- {{t 'file-detail.registration-date'}}
-
- {{moment-format manager.target.dateRegistered 'MMMM D, YYYY'}}
-
- {{/if}}
- {{#if @manager.node.dateWithdrawn}}
- {{t 'file-detail.withdrawal-date'}}
-
- {{moment-format manager.target.dateWithdrawn 'MMMM D, YYYY'}}
-
- {{/if}}
- {{#if manager.targetIdentifiers}}
- {{#each manager.targetIdentifiers as |identifier| }}
-
-
- {{identifier.category}}
-
-
-
- {{/each}}
- {{/if}}
-
- {{#unless manager.isAnonymous}}
- {{t 'file-detail.contributors'}}
-
- {{/unless}}
- {{/if}}
- {{/if}}
-
-
- {{/if}}
-
- <:rightButtons>
- {{#if this.media.isMobile}}
-
-
-
- {{/if}}
-
-
-
- {{#if this.model.shouldShowRevisions}}
-
-
-
- {{/if}}
- {{#if this.model.shouldShowTags}}
-
-
-
- {{/if}}
-
-
+{{page-title this.model.displayName}}
+{{ outlet }}
diff --git a/app/guid-node/metadata/add/controller.ts b/app/guid-node/metadata/add/controller.ts
new file mode 100644
index 00000000000..12a8691ce99
--- /dev/null
+++ b/app/guid-node/metadata/add/controller.ts
@@ -0,0 +1,42 @@
+import Controller from '@ember/controller';
+import { inject as service } from '@ember/service';
+import Media from 'ember-responsive';
+import config from 'ember-osf-web/config/environment';
+import { action } from '@ember/object';
+import { tracked } from '@glimmer/tracking';
+import RouterService from '@ember/routing/router-service';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+import Intl from 'ember-intl/services/intl';
+
+export default class GuidMetadataAdd extends Controller {
+ @service media!: Media;
+ @service router!: RouterService;
+ @service intl!: Intl;
+
+ supportEmail = config.support.supportEmail;
+
+ @tracked displaySelectionOptions = true;
+ @tracked selectedTemplate?: CedarMetadataTemplateModel;
+
+ @action
+ selectTemplate(cedarMetadataTemplate: CedarMetadataTemplateModel): void {
+ this.displaySelectionOptions = false;
+ this.selectedTemplate = cedarMetadataTemplate;
+ }
+
+ @action
+ closeCedarEditor(): void {
+ this.displaySelectionOptions = true;
+ this.selectedTemplate = undefined;
+ }
+
+ get tabTitle(): string {
+ const translation = this.displaySelectionOptions ? 'metadata.add-flow.tab-title-select' :
+ 'metadata.add-flow.tab-title-add';
+ return this.intl.t(translation);
+ }
+
+ get isMobile() {
+ return this.media.isMobile;
+ }
+}
diff --git a/app/guid-node/metadata/add/route.ts b/app/guid-node/metadata/add/route.ts
new file mode 100644
index 00000000000..e2bba245cb6
--- /dev/null
+++ b/app/guid-node/metadata/add/route.ts
@@ -0,0 +1,37 @@
+import Store from '@ember-data/store';
+import Route from '@ember/routing/route';
+import { inject as service } from '@ember/service';
+import GuidMetadataAdd from 'ember-osf-web/guid-node/metadata/add/controller';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+
+
+export default class GuidMetadataAddRoute extends Route {
+ @service store!: Store;
+
+ async model() {
+ const parentModel = await this.modelFor('guid-node.metadata');
+ const templates = await this.store.query('cedar-metadata-template', {
+ adapterOptions: { sort: 'schema_name' },
+ });
+
+ const cedarMetadataRecords = await parentModel.target.queryHasMany('cedarMetadataRecords', {
+ embed: 'template',
+ 'page[size]': 20,
+ });
+
+ for(const cedarMetadataRecord of cedarMetadataRecords) {
+ const template = await cedarMetadataRecord.template as CedarMetadataTemplateModel;
+ template.recordCreated = true;
+ cedarMetadataRecord.templateName = template.schemaName;
+ }
+
+ return {
+ target: parentModel.target,
+ templates,
+ };
+ }
+
+ deactivate() {
+ (this.controller as GuidMetadataAdd).displaySelectionOptions = true;
+ }
+}
diff --git a/app/guid-node/metadata/add/styles.scss b/app/guid-node/metadata/add/styles.scss
new file mode 100644
index 00000000000..cbb36b2b98d
--- /dev/null
+++ b/app/guid-node/metadata/add/styles.scss
@@ -0,0 +1,56 @@
+// stylelint-disable max-nesting-depth, selector-max-compound-selectors
+
+.metadata-add-container {
+ margin: 30px;
+ padding-top: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .header-container {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ margin-bottom: 30px;
+
+ .header,
+ .explanation {
+ width: 100%;
+ margin-bottom: 30px;
+ }
+
+ .available-templates {
+ width: 100%;
+ font-weight: bold;
+ }
+ }
+
+ .template-container {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ }
+
+ &.mobile {
+ margin-top: 0;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 0;
+
+ .header-container {
+ flex-direction: column;
+ align-items: flex-start;
+ margin-bottom: 10px;
+
+ .header {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/app/guid-node/metadata/add/template.hbs b/app/guid-node/metadata/add/template.hbs
new file mode 100644
index 00000000000..4aef1c5d9a3
--- /dev/null
+++ b/app/guid-node/metadata/add/template.hbs
@@ -0,0 +1,18 @@
+{{page-title this.tabTitle}}
+
+ {{#if this.displaySelectionOptions}}
+
+ {{else}}
+
+ {{/if}}
+
+
diff --git a/app/guid-node/metadata/detail/controller.ts b/app/guid-node/metadata/detail/controller.ts
new file mode 100644
index 00000000000..3b71652a093
--- /dev/null
+++ b/app/guid-node/metadata/detail/controller.ts
@@ -0,0 +1,12 @@
+import Controller from '@ember/controller';
+import { inject as service } from '@ember/service';
+import Media from 'ember-responsive';
+
+export default class GuidMetadataDetail extends Controller {
+ @service media!: Media;
+
+
+ get isMobile() {
+ return this.media.isMobile;
+ }
+}
diff --git a/app/guid-node/metadata/detail/route.ts b/app/guid-node/metadata/detail/route.ts
new file mode 100644
index 00000000000..b8e2be7dbb9
--- /dev/null
+++ b/app/guid-node/metadata/detail/route.ts
@@ -0,0 +1,53 @@
+import Store from '@ember-data/store';
+import Route from '@ember/routing/route'; import RouterService from '@ember/routing/router-service';
+import { inject as service } from '@ember/service';
+import CedarMetadataRecordModel from 'ember-osf-web/models/cedar-metadata-record';
+import CedarMetadataTemplateModel from 'ember-osf-web/models/cedar-metadata-template';
+
+export default class MetadataDetailRoute extends Route {
+ @service store!: Store;
+ @service router!: RouterService;
+
+ async model(params: { recordId: string}) {
+ const parentModel = this.modelFor('guid-node.metadata');
+ let defaultIndex = 0;
+
+ const cedarMetadataRecords = await parentModel.target.queryHasMany('cedarMetadataRecords', {
+ embed: 'template',
+ 'page[size]': 20,
+ });
+
+ for(const cedarMetadataRecord of cedarMetadataRecords) {
+ const template = await cedarMetadataRecord.template as CedarMetadataTemplateModel;
+ template.recordCreated = true;
+ cedarMetadataRecord.templateName = template.schemaName;
+ }
+
+ cedarMetadataRecords.sort(
+ (a: CedarMetadataRecordModel, b: CedarMetadataRecordModel) =>
+ a.templateName > b.templateName ? 1 : -1,
+ );
+
+ if (params.recordId) {
+ let index = 0;
+ for(const cedarMetadataRecord of cedarMetadataRecords) {
+ if (cedarMetadataRecord.id === params.recordId) {
+ defaultIndex = index + 1;
+ }
+ index++;
+ }
+ }
+
+ if (defaultIndex > 0) {
+ const selected = cedarMetadataRecords.splice(defaultIndex - 1, 1);
+ cedarMetadataRecords.unshift(selected[0]);
+ defaultIndex = 1;
+ }
+
+ return {
+ target: parentModel.target,
+ cedarMetadataRecords,
+ defaultIndex,
+ };
+ }
+}
diff --git a/app/guid-node/metadata/detail/styles.scss b/app/guid-node/metadata/detail/styles.scss
new file mode 100644
index 00000000000..61214e771ae
--- /dev/null
+++ b/app/guid-node/metadata/detail/styles.scss
@@ -0,0 +1,26 @@
+// stylelint-disable max-nesting-depth, selector-max-compound-selectors
+
+.metadata-container {
+ margin: 30px;
+ padding: 30px;
+ padding-top: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .metadata-tab-container {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+ }
+
+ &.mobile {
+ margin-top: 0;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 0;
+ }
+}
diff --git a/app/guid-node/metadata/detail/template.hbs b/app/guid-node/metadata/detail/template.hbs
new file mode 100644
index 00000000000..04d2592abbc
--- /dev/null
+++ b/app/guid-node/metadata/detail/template.hbs
@@ -0,0 +1,13 @@
+
diff --git a/app/guid-node/metadata/index/route.ts b/app/guid-node/metadata/index/route.ts
new file mode 100644
index 00000000000..bffd2c74b41
--- /dev/null
+++ b/app/guid-node/metadata/index/route.ts
@@ -0,0 +1,8 @@
+import Route from '@ember/routing/route';
+
+
+export default class MetadataIndexRoute extends Route {
+ model() {
+ this.replaceWith('guid-node.metadata.detail', 'osf');
+ }
+}
diff --git a/app/guid-node/metadata/route.ts b/app/guid-node/metadata/route.ts
new file mode 100644
index 00000000000..33b459784f4
--- /dev/null
+++ b/app/guid-node/metadata/route.ts
@@ -0,0 +1,18 @@
+import Store from '@ember-data/store';
+import Route from '@ember/routing/route';
+import RouterService from '@ember/routing/router-service';
+import { inject as service } from '@ember/service';
+
+export default class MetadataDetailRoute extends Route {
+ @service store!: Store;
+ @service router!: RouterService;
+
+ async model() {
+ const guidNode = this.modelFor('guid-node');
+ const target = await guidNode.taskInstance;
+
+ return {
+ target,
+ };
+ }
+}
diff --git a/app/guid-node/metadata/styles.scss b/app/guid-node/metadata/styles.scss
deleted file mode 100644
index ddafcea6b76..00000000000
--- a/app/guid-node/metadata/styles.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.container {
- margin: 10px 40px;
-}
diff --git a/app/guid-node/metadata/template.hbs b/app/guid-node/metadata/template.hbs
index 5e7b5d0cd84..f3dc9c57c84 100644
--- a/app/guid-node/metadata/template.hbs
+++ b/app/guid-node/metadata/template.hbs
@@ -1,9 +1,2 @@
-
-
- {{#if manager.isGatheringData}}
-
- {{else}}
-
- {{/if}}
-
-
\ No newline at end of file
+{{page-title (t 'metadata.tab-title')}}
+{{ outlet }}
diff --git a/app/guid-node/route.ts b/app/guid-node/route.ts
index ec0a653007a..2dd4a16eb48 100644
--- a/app/guid-node/route.ts
+++ b/app/guid-node/route.ts
@@ -1,10 +1,20 @@
+import { action } from '@ember/object';
+import RouterService from '@ember/routing/router-service';
+import { inject as service } from '@ember/service';
import GuidRoute from 'ember-osf-web/resolve-guid/guid-route';
+import { notFoundURL } from 'ember-osf-web/utils/clean-url';
export default class GuidNode extends GuidRoute {
+ @service router!: RouterService;
modelName(): 'node' {
return 'node';
}
+ @action
+ error() {
+ this.router.transitionTo('not-found', notFoundURL(window.location.pathname));
+ }
+
adapterOptions() {
return {
query: {
diff --git a/app/guid-node/template.hbs b/app/guid-node/template.hbs
index e6477f938fb..0c6ab9387d6 100644
--- a/app/guid-node/template.hbs
+++ b/app/guid-node/template.hbs
@@ -3,6 +3,7 @@