Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 2.11.0-privacyPolicy
  • APIv2
  • Docs/Setup
  • Experiment/fix-debugging
  • Experimental/Heinrichs-cypress
  • Feature/xxxx-turnOffDataPub
  • Fix/xxxx-ToS400Error
  • Fix/xxxx-migrateLogin
  • Fix/xxxx-tokenUploadButton
  • Hotfix/0038-correctDownload
  • Hotfix/1917-PublicFilesVisibility
  • Hotfix/1963-fixOrganizationField
  • Hotfix/2015-PublicFilesVisibility
  • Hotfix/2130-uiv2ContactChange
  • Hotfix/2144-invitationCall
  • Hotfix/2150-fixUpload
  • Hotfix/2160-userOrgsInst
  • Hotfix/2190-requiredFieldsForUserProfile
  • Hotfix/2196-RCVTableTranslation
  • Hotfix/2212-fixFiles
  • Hotfix/2226-userProfileSaveButton
  • Hotfix/2232-dependencyFix
  • Hotfix/2233-fixMe
  • Hotfix/2258-saveButtonWorksAsExpected
  • Hotfix/2296-selectedValuesNotReturned
  • Hotfix/2308-defaultLicense
  • Hotfix/2335-fixingSearchRCV
  • Hotfix/2353-dropShape
  • Hotfix/2370-fixDeleteButton
  • Hotfix/2378-linkedFix
  • Hotfix/2379-filesDragAndDrop
  • Hotfix/2382-guestStillBuggy
  • Hotfix/2384-guestsAndLinked
  • Hotfix/2427-adminTrouble
  • Hotfix/2459-EncodingPath
  • Hotfix/2465-orcidLink
  • Hotfix/2465-orcidLink-v1.25.1
  • Hotfix/2504-formGen
  • Hotfix/2541-resCreate
  • Hotfix/2601-correctMetadataIdentity
  • Hotfix/2611-feedback
  • Hotfix/2618-turtle
  • Hotfix/2681-validationErrors
  • Hotfix/2684-correctEncoding
  • Hotfix/2684-fixSubMetadata
  • Hotfix/2713-validateEntryName
  • Hotfix/2734-allowEmptyLicense
  • Hotfix/2765-encodingAgain
  • Hotfix/2852-adaptTextForToSUi
  • Hotfix/2853-optimizationV4
  • Hotfix/2943-reloadingResources
  • Hotfix/2943-searchHighlighting
  • Hotfix/2957-styleAndUpgrade
  • Hotfix/2971-fixTextInDataPub
  • Hotfix/2989-cookieLength
  • Hotfix/662-keepSidebarExpanded
  • Hotfix/xxxx-correctLinking
  • Hotfix/xxxx-folderRecursive
  • Hotfix/xxxx-fullscreenCss
  • Hotfix/xxxx-homepageDisplay
  • Hotfix/xxxx-liveReleaseFixes
  • Hotfix/xxxx-partnerProjects
  • Hotfix/xxxx-workingFileIndex
  • Issue/1782-structualDataIntegration
  • Issue/1792-newMetadataStructure
  • Issue/1822-coscineUIv2App
  • Issue/1824-componentsUIv2
  • Issue/1824-routerAdditions
  • Issue/1825-codeQualityPipelines
  • Issue/1833-newLogin
  • Issue/1843-multipleFilesValidation
  • Issue/1860-searchScoping
  • Issue/1861-searchMetadata
  • Issue/1862-searchFacets
  • Issue/1863-paginationForSearch
  • Issue/1926-userProfile
  • Issue/1927-projectAppMigration
  • Issue/1928-sidebarmenuAddition
  • Issue/1929-vuexToPinia
  • Issue/1938-internalHandling
  • Issue/1951-quotaImplementation
  • Issue/1953-owlImports
  • Issue/1957-resourceAppMigration
  • Issue/1957-resourceAppMigrationNew
  • Issue/1962-SearchAppUI2
  • Issue/1964-tokenExpiryUIv2
  • Issue/1965-userListMigration
  • Issue/1970-breadcrumbs
  • Issue/1971-projectEditCreateMigration
  • Issue/1972-homeDepot
  • Issue/1974-shibbolethLogout
  • Issue/1976-resouceCreationVaildEmail
  • Issue/1979-supportAdminUIv2Migration
  • Issue/1980-userManagement
  • Issue/1985-adaptSidebar
  • Issue/2002-migrateResourceCreate
  • Issue/2003-resourceSettings
  • Issue/2008-quotaManagement
  • Issue/2011-pathConfig
  • Issue/2016-BannerMigration
  • 1.28.0-pilot
  • v1.0.0
  • v1.1.0
  • v1.10.0
  • v1.10.1
  • v1.10.2
  • v1.10.3
  • v1.11.0
  • v1.11.1
  • v1.11.2
  • v1.11.3
  • v1.11.4
  • v1.11.5
  • v1.11.6
  • v1.11.7
  • v1.12.0
  • v1.13.0
  • v1.14.0
  • v1.14.1
  • v1.14.2
  • v1.14.3
  • v1.15.0
  • v1.15.1
  • v1.16.0
  • v1.16.1
  • v1.16.2
  • v1.16.3
  • v1.17.0
  • v1.17.1
  • v1.17.2
  • v1.18.0
  • v1.18.1
  • v1.19.0
  • v1.2.0
  • v1.20.0
  • v1.20.1
  • v1.20.2
  • v1.20.3
  • v1.20.4
  • v1.20.5
  • v1.21.0
  • v1.22.0
  • v1.22.1
  • v1.22.2
  • v1.23.0
  • v1.23.1
  • v1.23.2
  • v1.23.3
  • v1.23.4
  • v1.23.5
  • v1.23.6
  • v1.23.6-patch-2417-2427
  • v1.24.0
  • v1.24.1
  • v1.25.0
  • v1.25.1
  • v1.26.0
  • v1.26.1
  • v1.27.0
  • v1.27.1
  • v1.27.1-pilot
  • v1.28.0
  • v1.29.0
  • v1.29.1
  • v1.29.2
  • v1.3.0
  • v1.30.0
  • v1.30.1
  • v1.30.2
  • v1.31.0
  • v1.32.0
  • v1.4.0
  • v1.4.1
  • v1.5.0
  • v1.6.0
  • v1.6.1
  • v1.6.2
  • v1.7.0
  • v1.8.0
  • v1.8.1
  • v1.8.2
  • v1.9.0
  • v2.0.0
  • v2.1.0
  • v2.10.0
  • v2.10.1
  • v2.11.0
  • v2.12.0
  • v2.12.1
  • v2.12.2
  • v2.12.3
  • v2.12.4
  • v2.12.5
  • v2.13.0
  • v2.13.1
  • v2.13.2
  • v2.13.3
  • v2.13.4
  • v2.14.0
  • v2.15.0
200 results

Target

Select target project
  • coscine/frontend/apps/ui
1 result
Select Git revision
  • 2.11.0-privacyPolicy
  • APIv2
  • Docs/Setup
  • Experiment/fix-debugging
  • Experimental/Heinrichs-cypress
  • Feature/xxxx-turnOffDataPub
  • Fix/xxxx-ToS400Error
  • Fix/xxxx-migrateLogin
  • Fix/xxxx-tokenUploadButton
  • Hotfix/0038-correctDownload
  • Hotfix/1917-PublicFilesVisibility
  • Hotfix/1963-fixOrganizationField
  • Hotfix/2015-PublicFilesVisibility
  • Hotfix/2130-uiv2ContactChange
  • Hotfix/2144-invitationCall
  • Hotfix/2150-fixUpload
  • Hotfix/2160-userOrgsInst
  • Hotfix/2190-requiredFieldsForUserProfile
  • Hotfix/2196-RCVTableTranslation
  • Hotfix/2212-fixFiles
  • Hotfix/2226-userProfileSaveButton
  • Hotfix/2232-dependencyFix
  • Hotfix/2233-fixMe
  • Hotfix/2258-saveButtonWorksAsExpected
  • Hotfix/2296-selectedValuesNotReturned
  • Hotfix/2308-defaultLicense
  • Hotfix/2335-fixingSearchRCV
  • Hotfix/2353-dropShape
  • Hotfix/2370-fixDeleteButton
  • Hotfix/2378-linkedFix
  • Hotfix/2379-filesDragAndDrop
  • Hotfix/2382-guestStillBuggy
  • Hotfix/2384-guestsAndLinked
  • Hotfix/2427-adminTrouble
  • Hotfix/2459-EncodingPath
  • Hotfix/2465-orcidLink
  • Hotfix/2465-orcidLink-v1.25.1
  • Hotfix/2504-formGen
  • Hotfix/2541-resCreate
  • Hotfix/2601-correctMetadataIdentity
  • Hotfix/2611-feedback
  • Hotfix/2618-turtle
  • Hotfix/2681-validationErrors
  • Hotfix/2684-correctEncoding
  • Hotfix/2684-fixSubMetadata
  • Hotfix/2713-validateEntryName
  • Hotfix/2734-allowEmptyLicense
  • Hotfix/2765-encodingAgain
  • Hotfix/2852-adaptTextForToSUi
  • Hotfix/2853-optimizationV4
  • Hotfix/2943-reloadingResources
  • Hotfix/2943-searchHighlighting
  • Hotfix/2957-styleAndUpgrade
  • Hotfix/2971-fixTextInDataPub
  • Hotfix/2989-cookieLength
  • Hotfix/662-keepSidebarExpanded
  • Hotfix/xxxx-correctLinking
  • Hotfix/xxxx-folderRecursive
  • Hotfix/xxxx-fullscreenCss
  • Hotfix/xxxx-homepageDisplay
  • Hotfix/xxxx-liveReleaseFixes
  • Hotfix/xxxx-partnerProjects
  • Hotfix/xxxx-workingFileIndex
  • Issue/1782-structualDataIntegration
  • Issue/1792-newMetadataStructure
  • Issue/1822-coscineUIv2App
  • Issue/1824-componentsUIv2
  • Issue/1824-routerAdditions
  • Issue/1825-codeQualityPipelines
  • Issue/1833-newLogin
  • Issue/1843-multipleFilesValidation
  • Issue/1860-searchScoping
  • Issue/1861-searchMetadata
  • Issue/1862-searchFacets
  • Issue/1863-paginationForSearch
  • Issue/1926-userProfile
  • Issue/1927-projectAppMigration
  • Issue/1928-sidebarmenuAddition
  • Issue/1929-vuexToPinia
  • Issue/1938-internalHandling
  • Issue/1951-quotaImplementation
  • Issue/1953-owlImports
  • Issue/1957-resourceAppMigration
  • Issue/1957-resourceAppMigrationNew
  • Issue/1962-SearchAppUI2
  • Issue/1964-tokenExpiryUIv2
  • Issue/1965-userListMigration
  • Issue/1970-breadcrumbs
  • Issue/1971-projectEditCreateMigration
  • Issue/1972-homeDepot
  • Issue/1974-shibbolethLogout
  • Issue/1976-resouceCreationVaildEmail
  • Issue/1979-supportAdminUIv2Migration
  • Issue/1980-userManagement
  • Issue/1985-adaptSidebar
  • Issue/2002-migrateResourceCreate
  • Issue/2003-resourceSettings
  • Issue/2008-quotaManagement
  • Issue/2011-pathConfig
  • Issue/2016-BannerMigration
  • 1.28.0-pilot
  • v1.0.0
  • v1.1.0
  • v1.10.0
  • v1.10.1
  • v1.10.2
  • v1.10.3
  • v1.11.0
  • v1.11.1
  • v1.11.2
  • v1.11.3
  • v1.11.4
  • v1.11.5
  • v1.11.6
  • v1.11.7
  • v1.12.0
  • v1.13.0
  • v1.14.0
  • v1.14.1
  • v1.14.2
  • v1.14.3
  • v1.15.0
  • v1.15.1
  • v1.16.0
  • v1.16.1
  • v1.16.2
  • v1.16.3
  • v1.17.0
  • v1.17.1
  • v1.17.2
  • v1.18.0
  • v1.18.1
  • v1.19.0
  • v1.2.0
  • v1.20.0
  • v1.20.1
  • v1.20.2
  • v1.20.3
  • v1.20.4
  • v1.20.5
  • v1.21.0
  • v1.22.0
  • v1.22.1
  • v1.22.2
  • v1.23.0
  • v1.23.1
  • v1.23.2
  • v1.23.3
  • v1.23.4
  • v1.23.5
  • v1.23.6
  • v1.23.6-patch-2417-2427
  • v1.24.0
  • v1.24.1
  • v1.25.0
  • v1.25.1
  • v1.26.0
  • v1.26.1
  • v1.27.0
  • v1.27.1
  • v1.27.1-pilot
  • v1.28.0
  • v1.29.0
  • v1.29.1
  • v1.29.2
  • v1.3.0
  • v1.30.0
  • v1.30.1
  • v1.30.2
  • v1.31.0
  • v1.32.0
  • v1.4.0
  • v1.4.1
  • v1.5.0
  • v1.6.0
  • v1.6.1
  • v1.6.2
  • v1.7.0
  • v1.8.0
  • v1.8.1
  • v1.8.2
  • v1.9.0
  • v2.0.0
  • v2.1.0
  • v2.10.0
  • v2.10.1
  • v2.11.0
  • v2.12.0
  • v2.12.1
  • v2.12.2
  • v2.12.3
  • v2.12.4
  • v2.12.5
  • v2.13.0
  • v2.13.1
  • v2.13.2
  • v2.13.3
  • v2.13.4
  • v2.14.0
  • v2.15.0
200 results
Show changes
Commits on Source (5)
Showing
with 3765 additions and 40 deletions
packageExtensions:
"@vue/cli-service@*":
peerDependencies:
"@vue/cli-plugin-eslint": "*"
"@vue/cli-plugin-router": "*"
"@vue/cli-plugin-typescript": "*"
"fork-ts-checker-webpack-plugin@*":
dependencies:
"vue-template-compiler": "*"
......
{
"name": "ui",
"version": "1.4.1",
"version": "1.5.0",
"private": true,
"scripts": {
"dev": "vite",
......@@ -11,12 +11,14 @@
},
"dependencies": {
"@coscine/api-client": "^1.5.1",
"@coscine/form-generator": "^1.18.0",
"@vueuse/core": "^6.5.3",
"axios": "^0.26.1",
"bootstrap": "^4.6.1",
"bootstrap-icons": "^1.8.1",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.21.1",
"file-saver": "^2.0.5",
"http-status-codes": "^2.2.0",
"jose": "^4.6.0",
"jquery": "^3.6.0",
......@@ -24,6 +26,7 @@
"lodash": "^4.17.21",
"moment": "^2.29.1",
"pinia": "^2.0.12",
"rdf-validate-shacl": "^0.4.3",
"sass": "^1.49.9",
"semantic-release": "^19.0.2",
"uuid": "^8.3.2",
......@@ -43,7 +46,9 @@
"@semantic-release/gitlab": "^7.0.4",
"@semantic-release/npm": "^8.0.3",
"@semantic-release/release-notes-generator": "^10.0.3",
"@types/file-saver": "^2.0.5",
"@types/lodash": "^4.14.178",
"@types/rdf-validate-shacl": "^0.4.0",
"@types/uuid": "^8.3.4",
"@types/vue-select": "^3.16.0",
"@types/vuelidate": "^0.7.15",
......
......@@ -52,8 +52,9 @@ export default defineComponent({
},
});
</script>
<style>
.mandatory .col-form-label:after {
<style scoped>
.mandatory >>> .col-form-label:after {
content: " *";
color: #a70619;
}
......
......@@ -14,7 +14,10 @@ import { useProjectStore } from "@/modules/project/store";
// import the main store
import { useMainStore } from "@/store/index";
import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { VisitedResourceObject } from "./types";
import type { ResourceTypeInformation } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import VueI18n from "vue-i18n";
import { cloneDeep } from "lodash";
export default defineComponent({
setup() {
......@@ -24,21 +27,35 @@ export default defineComponent({
return { mainStore, resourceStore, projectStore };
},
i18n: { messages: ResourceI18nMessages },
i18n: { messages: cloneDeep(ResourceI18nMessages) },
created() {
this.initialize();
},
computed: {
resource(): ResourceObject | null {
resource(): VisitedResourceObject | null {
return this.resourceStore.currentResource;
},
resourceTypeInformation(): null | undefined | ResourceTypeInformation {
if (this.resourceStore.resourceTypes && this.resource) {
return this.resourceStore.resourceTypes.find(
(resourceType) => resourceType.id === this.resource?.type?.id
);
}
return null;
},
moduleIsReady(): boolean {
return true;
},
},
watch: {
resourceTypeInformation() {
this.setI18n();
},
},
methods: {
async initialize() {
// Resource may be unset (e.g. when entering from a direct link)
......@@ -46,6 +63,61 @@ export default defineComponent({
this.resource,
this.$router.currentRoute
);
if (this.resource) {
if (!this.resourceStore.currentFullApplicationProfile) {
this.resourceStore.retrieveApplicationProfile(this.resource);
}
if (
!this.resourceStore.currentUsedQuota &&
this.resourceTypeInformation?.isQuotaAdjustable
) {
this.resourceStore.retrieveUsedQuota(this.resource);
}
}
this.setI18n();
},
setI18n() {
this.$i18n.mergeLocaleMessage("de", cloneDeep(ResourceI18nMessages.de));
this.$i18n.mergeLocaleMessage("en", cloneDeep(ResourceI18nMessages.en));
if (
this.resourceTypeInformation &&
this.resourceTypeInformation.displayName
) {
if (ResourceI18nMessages.de.resourceType) {
const germanResourceTypeMessageObject = ResourceI18nMessages.de
.resourceType as VueI18n.LocaleMessageObject;
if (
germanResourceTypeMessageObject[
this.resourceTypeInformation.displayName
]
) {
const resourceTypeDefinition = germanResourceTypeMessageObject[
this.resourceTypeInformation.displayName
] as VueI18n.LocaleMessageObject;
this.$i18n.mergeLocaleMessage(
"de",
cloneDeep(resourceTypeDefinition)
);
}
}
if (ResourceI18nMessages.en.resourceType) {
const englishResourceTypeMessageObject = ResourceI18nMessages.en
.resourceType as VueI18n.LocaleMessageObject;
if (
englishResourceTypeMessageObject[
this.resourceTypeInformation.displayName
]
) {
const resourceTypeDefinition = englishResourceTypeMessageObject[
this.resourceTypeInformation.displayName
] as VueI18n.LocaleMessageObject;
this.$i18n.mergeLocaleMessage(
"en",
cloneDeep(resourceTypeDefinition)
);
}
}
}
},
},
});
......
This diff is collapsed.
<template>
<b-row class="headerRow">
<div class="col-sm-7 file-view-header">
<span>
<p
class="h4"
v-if="
resource &&
resource.type &&
resource.type.displayName &&
resource.displayName
"
>
{{
$parent.$parent.$parent.$t(
"ResourceTypes." + resource.type.displayName + ".displayName"
)
}}: {{ resource.displayName }}
</p>
</span>
<b-icon
id="resourceDetails"
icon="info-circle"
:title="$parent.$parent.$parent.$t('page.resource.info')"
/>
<b-popover
v-if="resource"
over
custom-class="b-popover"
target="resourceDetails"
triggers="hover focus"
placement="bottom"
>
<template v-slot:title
><b>{{ resource.displayName }}</b></template
>
<div v-if="resource.displayName">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.displayName") }}:
</b> </span
><span>{{ resource.displayName }}</span>
</div>
<div v-if="resource.pid">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.PID") }}:
</b> </span
><span>{{ resource.pid }}</span>
</div>
<div v-if="resource.description">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.description") }}:
</b> </span
><span>{{ resource.description }}</span
><br />
</div>
<div v-if="resource.disciplines && resource.disciplines.length > 0">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.disciplines") }}:
</b>
</span>
<ul>
<li
v-for="discipline in resource.disciplines"
v-bind:key="discipline.id"
>
<div v-if="$i18n.locale === 'de'">
{{ discipline.displayNameDe }}
</div>
<div v-else>
{{ discipline.displayNameEn }}
</div>
</li>
</ul>
</div>
<div v-if="resource.keywords && resource.keywords.length > 0">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.keywords") }}:
</b> </span
><br />
<ul>
<li v-for="keyword in resource.keywords" v-bind:key="keyword">
{{ keyword }}
</li>
</ul>
</div>
<div v-if="resource.visibility">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.visibility") }}:
</b> </span
><span>{{ resource.visibility.displayName }}</span
><br />
</div>
<div v-if="resource.license">
<span
><b
>{{
$parent.$parent.$parent.$t("page.resource.resourceLicense")
}}:
</b> </span
><span>{{ resource.license.displayName }}</span
><br />
</div>
<div v-if="resource.usageRights">
<span
><b
>{{ $parent.$parent.$parent.$t("page.resource.usageRights") }}:
</b> </span
><span>{{ resource.usageRights }}</span
><br />
</div>
</b-popover>
<b-button
@click="edit"
:title="$parent.$parent.$parent.$t('page.resource.edit')"
class="btn btn-sm"
v-if="canEditResource"
>
<b-icon
icon="pencil-fill"
:title="$parent.$parent.$parent.$t('page.resource.edit')"
/>
</b-button>
<b-button
@click="upload"
:title="$parent.$parent.$parent.$t('page.resource.upload')"
class="btn btn-sm"
:disabled="isUploading || readOnly || (resource && resource.archived)"
>
<b-icon
icon="plus"
:title="$parent.$parent.$parent.$t('page.resource.upload')"
/>
</b-button>
<span v-if="resource && resource.archived" class="badgeWrap">
<b-badge pill variant="warning">{{ $t("default.archived") }}</b-badge>
</span>
</div>
<div class="col-sm-3">
<div
v-if="maxSize !== undefined && used !== undefined"
class="progressContainer"
>
<b-progress :max="maxSize">
<b-progress-bar :value="used">
<span v-if="used / maxSize >= 0.5">
<strong
>{{ formatBytes(used) }} / {{ formatBytes(maxSize) }}</strong
>
</span>
</b-progress-bar>
<b-progress-bar :value="maxSize - used" variant="secondary">
<span v-if="used / maxSize < 0.5">
<strong
>{{ formatBytes(used) }} / {{ formatBytes(maxSize) }}</strong
>
</span>
</b-progress-bar>
</b-progress>
</div>
</div>
<div class="col-sm-2 searchColumn">
<b-input-group>
<b-form-input
type="search"
id="filterInput"
:placeholder="
$parent.$parent.$parent.$t('page.resource.typeToSearch')
"
:value="value"
@input="$emit('input', $event)"
></b-form-input>
</b-input-group>
</div>
</b-row>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
// import the store for current module
import { useResourceStore } from "../store";
import { useProjectStore } from "@/modules/project/store";
// import the user store
import { useUserStore } from "@/modules/user/store";
// import the main store
import { useMainStore } from "@/store/index";
import { FileUtil } from "../utils/FileUtil";
import {
ProjectObject,
ProjectQuotaReturnObject,
UserObject,
} from "@coscine/api-client/dist/types/Coscine.Api.Project";
import router from "@/router";
import type { ResourceTypeInformation } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { VisitedResourceObject } from "../types";
export default defineComponent({
setup() {
const mainStore = useMainStore();
const resourceStore = useResourceStore();
const projectStore = useProjectStore();
const userStore = useUserStore();
return { mainStore, resourceStore, projectStore, userStore };
},
computed: {
isOwner(): boolean | undefined {
return this.projectStore.currentUserRoleIsOwner;
},
project(): null | ProjectObject {
return this.projectStore.currentProject;
},
quotas(): ProjectQuotaReturnObject[] | null {
return this.projectStore.currentQuotas;
},
resource(): null | VisitedResourceObject {
return this.resourceStore.currentResource;
},
resourceTypeInformation(): null | undefined | ResourceTypeInformation {
if (this.resourceStore.resourceTypes && this.resource) {
return this.resourceStore.resourceTypes.find(
(resourceType) => resourceType.id === this.resource?.type?.id
);
}
return null;
},
user(): null | UserObject {
return this.userStore.user;
},
canEditResource(): boolean {
if (this.resource && this.user) {
return this.resource.creator === this.user.id || this.isOwner === true;
}
return false;
},
readOnly(): boolean {
return this.resourceTypeInformation?.resourceContent?.readOnly === true;
},
maxSize(): number | undefined {
if (
this.resource &&
this.resource.resourceTypeOption &&
this.resource.resourceTypeOption.Size !== undefined
) {
return this.resource.resourceTypeOption.Size * 1024 * 1024 * 1024;
}
return undefined;
},
used(): number | undefined {
if (this.resourceStore.currentUsedQuota) {
return this.resourceStore.currentUsedQuota;
}
return undefined;
},
},
name: "Header",
props: {
isUploading: Boolean,
value: String,
},
methods: {
edit() {
if (
this.resource &&
this.resource.id &&
this.project &&
this.project.slug
) {
router.push({
name: "resource-settings",
params: {
slug: this.project.slug,
guid: this.resource.id,
},
});
}
},
upload() {
this.$emit("clickFileSelect");
},
formatBytes(bytes: number) {
return FileUtil.formatBytes(bytes);
},
},
});
</script>
<style scoped>
.file-view-header {
padding-left: 25px;
}
.searchColumn {
padding-right: 25px;
}
.file-view-header >>> p.h4 {
display: inline-block;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - 11rem);
}
.file-view-header >>> svg {
vertical-align: top;
margin-left: 3px;
margin-right: 3px;
}
.file-view-header >>> button {
vertical-align: top;
margin: 0 4px 0px 4px;
}
.btn-sm {
min-width: 0;
width: 30px;
padding: 2px;
}
#resourceDetails:hover {
cursor: pointer;
}
.progress {
height: 1.15rem;
max-width: 15rem;
margin: 5px auto;
}
.progressContainer {
margin: 0 auto;
}
.b-popover {
max-width: 100%;
}
.badgeWrap >>> .badge {
vertical-align: top;
height: 1.3rem;
}
#filterInput {
max-height: 30px;
}
</style>
This diff is collapsed.
<template>
<span>
<coscine-form-group
:label="$parent.$parent.$parent.$t('page.resource.infoFileName')"
>
<div class="fileInfoField">
{{
!fileListEdit[currentFileId].name
? $parent.$parent.$parent.$t("page.resource.infoFileNoInformation")
: fileListEdit[currentFileId].name
}}
</div>
</coscine-form-group>
<coscine-form-group
:label="$parent.$parent.$parent.$t('page.resource.infoFileLastModified')"
>
<div class="fileInfoField">
{{
!fileListEdit[currentFileId].lastModified
? $parent.$parent.$parent.$t("page.resource.infoFileNoInformation")
: new Date(
fileListEdit[currentFileId].lastModified
).toLocaleDateString($i18n.locale)
}}
</div>
</coscine-form-group>
<coscine-form-group
:label="$parent.$parent.$parent.$t('page.resource.infoFileCreated')"
>
<div class="fileInfoField">
{{
!fileListEdit[currentFileId].created
? $parent.$parent.$parent.$t("page.resource.infoFileNoInformation")
: new Date(fileListEdit[currentFileId].created).toLocaleDateString(
$i18n.locale
)
}}
</div>
</coscine-form-group>
<coscine-form-group
:label="$parent.$parent.$parent.$t('page.resource.infoFileSize')"
>
<div class="fileInfoField">
{{
fileListEdit[currentFileId].size === undefined ||
fileListEdit[currentFileId].size === null
? $parent.$parent.$parent.$t("page.resource.infoFileNoInformation")
: fileListEdit[currentFileId].size + " Bytes"
}}
</div>
</coscine-form-group>
</span>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue-demi";
import type { FolderContent } from "../../utils/EntryDefinition";
export default defineComponent({
props: {
currentFileId: {
required: true,
type: Number,
},
fileListEdit: {
required: true,
type: Array as PropType<FolderContent[]>,
},
},
});
</script>
<style scoped>
.fileInfoField {
padding-top: calc(0.375rem + 1px);
padding-bottom: calc(0.375rem + 1px);
}
</style>
<template>
<b-row id="metadataManagerButtonRowBottom">
<span class="processStatement" v-if="isUploading"
>{{
totalNumberOfCurrentlyProcessedFiles - numberOfCurrentlyProcessedFiles
}}/{{ totalNumberOfCurrentlyProcessedFiles }}</span
>
<div
id="metadataManagerButtonRowBottomContainer"
:class="saveButtonDisabled ? 'buttondisabled' : ''"
>
<b-col>
<b-progress
v-if="isUploading"
class="metadataManagerButtonRowProgress"
:value="progressStatus"
max="100"
show-progress
animated
></b-progress>
</b-col>
<b-col id="metadataManagerButtonCol">
<b-button
id="metadataManagerButtonRowBottomSave"
class="metadataManagerButtonRowBottomSave"
variant="primary"
@click="
isUploading
? undefined
: !showDetail
? $emit('uploadPreparation')
: $emit('update')
"
:disabled="saveButtonDisabled"
><b-spinner label="Spinning" v-show="isUploading"></b-spinner
>{{
isUploading
? $parent.$parent.$parent.$t(
"page.resource.metadataManagerBtnSaving"
)
: !showDetail
? $parent.$parent.$parent.$t(
"page.resource.metadataManagerBtnUpload"
)
: $parent.$parent.$parent.$t(
"page.resource.metadataManagerBtnUpdate"
)
}}</b-button
>
</b-col>
</div>
</b-row>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
export default defineComponent({
props: {
isUploading: {
required: true,
type: Boolean,
},
numberOfCurrentlyProcessedFiles: {
required: true,
type: Number,
},
progressStatus: {
required: true,
type: Number,
},
showDetail: {
required: true,
type: Boolean,
},
saveButtonDisabled: {
required: true,
type: Boolean,
},
totalNumberOfCurrentlyProcessedFiles: {
required: true,
type: Number,
},
},
});
</script>
<style scoped>
#metadataManagerButtonRowBottom {
position: absolute;
bottom: 45px;
width: 100%;
}
#metadataManagerButtonRowBottom >>> #metadataManagerButtonRowBottomContainer {
display: inline-flex;
position: absolute;
right: 0px;
width: auto;
height: 33px;
}
#metadataManagerButtonRowBottom
>>> #metadataManagerButtonRowBottomContainer.buttondisabled {
cursor: not-allowed;
}
#metadataManagerButtonRowBottom
>>> .metadataManagerButtonRowBottomSave.disabled {
pointer-events: none;
}
#metadataManagerButtonRowBottom >>> .metadataManagerButtonRowProgress {
width: 350px;
margin-top: 13px;
}
#metadataManagerButtonRowBottom >>> .processStatement {
position: absolute;
top: 13px;
left: 20px;
}
button >>> span.spinner-border {
height: 15px;
width: 15px;
margin-right: 4px;
}
</style>
<template>
<b-row id="metadataManagerButtonRowTop" align-h="between">
<b-col>
<b-button
id="buttonSelectFiles"
variant="secondary"
@click="$emit('selectFiles')"
:placeholder="
$parent.$parent.$parent.$t(
'page.resource.metadataManagerBtnSelectFiles'
)
"
:disabled="isUploading || readOnly || (resource && resource.archived)"
autofocus
>{{
$parent.$parent.$parent.$t(
"page.resource.metadataManagerBtnSelectFiles"
)
}}
</b-button>
</b-col>
<b-col>
<b-input-group id="metadataManagerDropDownMenu" class="float-right">
<b-dropdown
size="sm"
right
id="addColumnDropDown"
:disabled="
!showDetail ||
readOnly ||
(resource && resource.archived) ||
shownFiles.length === 0
"
>
<b-dropdown-item
v-if="showDetail"
@click="$emit('showModalDeleteFolderContents')"
>{{ $t("buttons.delete") }}</b-dropdown-item
>
</b-dropdown>
<b-button
v-if="!editableDataUrl"
@click="$emit('download')"
:disabled="!showDetail || shownFiles.length === 0"
>{{
$parent.$parent.$parent.$t(
"page.resource.metadataManagerBtnDownload"
)
}}</b-button
>
</b-input-group>
</b-col>
</b-row>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue-demi";
import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { FolderContent } from "../../utils/EntryDefinition";
export default defineComponent({
props: {
editableDataUrl: {
required: true,
type: Boolean,
},
isUploading: {
required: true,
type: Boolean,
},
readOnly: {
required: true,
type: Boolean,
},
resource: {
required: true,
type: Object as PropType<ResourceObject>,
},
showDetail: {
required: true,
type: Boolean,
},
shownFiles: {
required: true,
type: Array as PropType<FolderContent[]>,
},
},
});
</script>
<style scoped>
#metadataManagerButtonRowTop {
margin-bottom: 5px;
}
#metadataManagerDropDownMenu {
margin-right: 5px;
width: auto;
}
</style>
<template>
<div>
<span v-if="editableDataUrl">
<coscine-form-group
:mandatory="true"
labelFor="dataUrl"
:label="$parent.$parent.$parent.$t('page.resource.dataUrl')"
>
<b-input-group>
<b-form-input
id="dataUrl"
@input="updateDataUrl(currentFolderContent, $event)"
:value="currentFolderContent.dataUrl"
:placeholder="$parent.$parent.$parent.$t('page.resource.dataUrl')"
:disabled="resource.archived || readOnly"
/>
<b-button id="URLBtn" @click="openURL" :disabled="!isValidUrl"
><b-icon-link-45deg />
</b-button>
</b-input-group>
</coscine-form-group>
</span>
<span v-if="editableKey">
<coscine-form-group
:mandatory="true"
labelFor="metadataKey"
:label="$parent.$parent.$parent.$t('page.resource.metadataKey')"
>
<b-form-input
@change="updateAbsolutePath(currentFolderContent, $event)"
:value="currentFolderContent.name"
:placeholder="$parent.$parent.$parent.$t('page.resource.metadataKey')"
:disabled="resource.archived || readOnly"
/>
</coscine-form-group>
</span>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue-demi";
import type {
FileInformation,
FolderContent,
} from "../../utils/EntryDefinition";
import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
export default defineComponent({
computed: {
isValidUrl(): boolean {
if (
!this.currentFolderContent ||
(this.currentFolderContent && this.currentFolderContent.isFolder)
) {
return false;
}
const dataUrl = this.currentFolderContent.dataUrl;
if (dataUrl === undefined) {
return false;
}
let url: URL;
const validUrl =
/^(http[s]?:\/\/){0,1}(www\.){0,1}[a-zA-Z0-9.-]+\.[a-zA-Z]{2,5}[.]{0,1}/;
try {
if (dataUrl.includes("://")) {
url = new URL(dataUrl);
} else {
url = new URL("http://" + dataUrl);
}
} catch {
return false;
}
return validUrl.test(url.toString());
},
},
props: {
currentFolderContent: {
required: true,
type: [Object] as PropType<FolderContent>,
},
editableDataUrl: {
required: true,
type: Boolean,
},
editableKey: {
required: true,
type: Boolean,
},
readOnly: {
required: true,
type: Boolean,
},
resource: {
required: true,
type: [Object] as PropType<ResourceObject>,
},
},
methods: {
openURL() {
if (
this.editableDataUrl &&
this.currentFolderContent &&
!this.currentFolderContent.isFolder
) {
let url = this.currentFolderContent.dataUrl;
if (url !== undefined && !url.includes("://")) {
url = "http://" + url;
}
const win = window.open(url, "_blank");
if (win !== null) {
win.focus();
}
}
},
updateDataUrl(entry: FileInformation, value: string) {
entry.dataUrl = value;
entry.size = value.length;
},
updateAbsolutePath(entry: FolderContent, value: string) {
entry.name = value;
entry.path = entry.path !== "" ? entry.path : "/";
entry.absolutePath = entry.path + entry.name;
},
},
});
</script>
<template>
<div>
<b-row
id="metadataManagerShownFilesTable"
v-show="showDetail || !editableDataUrl || !editableKey"
>
<b-col>
<b-input-group v-for="(item, index) in shownFiles" :key="index">
<b-button
@click="$emit('changeMetadata', index)"
variant="outline-secondary"
:pressed="currentFileId === index"
>{{ index + 1 }}</b-button
>
<b-button
@click="$emit('changeMetadata', index)"
class="metadataManagerFileListFileName"
:pressed="false"
variant="outline-secondary"
>{{ item.name
}}<b-spinner v-show="item.uploading" label="Spinning"></b-spinner
></b-button>
<b-button
class="deleteFolderContentFromList"
@click="$emit('removeElement', index)"
variant="outline-secondary"
:disabled="item.uploading"
>X</b-button
>
</b-input-group>
</b-col>
</b-row>
<b-row id="metadataManagerQuickAccess" v-show="shownFiles.length > 1">
<b-col>
<b-button
@click="$emit('loadAllFilesTab')"
:pressed="currentFileId === -1"
variant="outline-secondary"
>{{ $parent.$parent.$t("page.resource.allFiles") }}</b-button
>
<span v-if="shownFiles.length > 1 && shownFiles.length <= 10">
<b-button
v-for="(item, index) in shownFiles"
:key="index"
:pressed="currentFileId === index"
@click="$emit('changeMetadata', index)"
variant="outline-secondary"
class="metadataTabButton"
>{{ index + 1 }}</b-button
>
</span>
</b-col>
</b-row>
<b-row id="metadataManagerFileName" class="text-center">
<b-col>
<span
class="showSpaces"
v-if="
currentFileId >= 0 &&
currentFileId < shownFiles.length &&
currentFolderContent
"
>
{{ currentFolderContent.name }}
</span>
<span v-else-if="shownFiles.length > 0">{{
$parent.$parent.$t("page.resource.allFiles")
}}</span>
</b-col>
</b-row>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue-demi";
import type { FolderContent } from "../../utils/EntryDefinition";
export default defineComponent({
props: {
currentFileId: {
required: true,
type: Number,
},
currentFolderContent: {
type: [Object, undefined] as PropType<FolderContent | undefined>,
},
editableDataUrl: {
required: true,
type: Boolean,
},
editableKey: {
required: true,
type: Boolean,
},
showDetail: {
required: true,
type: Boolean,
},
shownFiles: {
required: true,
type: Array as PropType<FolderContent[]>,
},
},
});
</script>
<style scoped>
.metadataManagerFileListFileName {
text-overflow: ellipsis;
}
#metadataManagerFileName {
margin-top: 5px;
left: 0;
right: 0;
}
#metadataManagerFileName >>> span {
text-align: center;
font-weight: bold;
width: 100%;
}
#metadataManagerShownFilesTable {
margin-right: -10px;
}
#metadataManagerShownFilesTable >>> .col {
overflow-x: hidden;
overflow-y: auto;
max-height: 150px;
padding-right: 0px;
margin-right: 15px;
}
#metadataManagerShownFilesTable >>> .input-group {
flex-wrap: initial;
}
#metadataManagerShownFilesTable >>> .metadataManagerFileListFileName {
width: inherit;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-transform: none;
}
#metadataManagerShownFilesTable >>> .spinner-border {
margin-left: 5px;
}
#metadataManagerShownFilesTable >>> .deleteFolderContentFromList {
color: red;
}
#metadataManagerQuickAccess {
left: 0;
right: 0;
}
#metadataManagerQuickAccess >>> .btn {
margin-top: 5px;
margin-right: 5px;
}
.metadataTabButton {
max-width: inherit;
min-width: inherit;
width: inherit;
}
.showSpaces {
white-space: pre;
}
button >>> span.spinner-border {
height: 15px;
width: 15px;
margin-right: 4px;
}
</style>
<template>
<b-modal
id="modalDeleteFolderContents"
:visible="visible"
size="lg"
hide-footer
:title="
$parent.$parent.$parent.$t(
'page.resource.modalDeleteFolderContentsHeader'
)
"
@hidden="$emit('close', $event.target.value)"
@ok="$emit('ok', $event.target.value)"
@cancel="$emit('close', $event.target.value)"
@shown="$emit('shown', $event.target.value)"
>
<div>
{{
$parent.$parent.$parent.$t(
"page.resource.modalDeleteFolderContentsBody"
)
}}
</div>
<br />
<div
v-for="(item, index) in shownFiles"
:key="index"
class="font-weight-bold"
>
{{ item.name }}
</div>
<br />
<b-button
class="float-left"
@click="$emit('close', $event.target.value)"
autofocus
>{{ $t("buttons.cancel") }}</b-button
>
<b-button
class="float-right"
variant="danger"
@click="$emit('ok', $event.target.value)"
>{{ $t("buttons.delete") }}</b-button
>
</b-modal>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
export default defineComponent({
props: {
shownFiles: {
required: true,
type: Array,
},
visible: {
default: false,
type: Boolean,
},
},
});
</script>
<template>
<b-modal
id="modalSaveDuplicateFiles"
:visible="visible"
size="lg"
hide-footer
:title="
$parent.$parent.$parent.$t('page.resource.modalSaveDuplicateFilesHeader')
"
@hidden="$emit('close', $event.target.value)"
@ok="$emit('ok', $event.target.value)"
@cancel="$emit('close', $event.target.value)"
@shown="$emit('shown', $event.target.value)"
>
<div>
{{
$parent.$parent.$parent.$t("page.resource.modalSaveDuplicateFilesBody")
}}
</div>
<br />
<div
v-for="(item, index) in uploadFileListReplaceFiles"
:key="index"
class="font-weight-bold"
>
{{ item.name }}
</div>
<br />
<div>
<b-button
class="float-left"
@click="$emit('close', $event.target.value)"
autofocus
>{{
$parent.$parent.$parent.$t(
"page.resource.modalSaveDuplicateFilesBtnCancel"
)
}}</b-button
>
<b-button
class="modalButtonFloatCenter"
@click="$emit('skip', $event.target.value)"
>{{
$parent.$parent.$parent.$t(
"page.resource.modalSaveDuplicateFilesBtnSkip"
)
}}</b-button
>
<b-button
class="float-right"
style="justify-content: flex-end"
@click="$emit('ok', $event.target.value)"
>{{
$parent.$parent.$parent.$t(
"page.resource.modalSaveDuplicateFilesBtnOverwrite"
)
}}</b-button
>
</div>
</b-modal>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
export default defineComponent({
props: {
uploadFileListReplaceFiles: {
required: true,
type: Array,
},
visible: {
default: false,
type: Boolean,
},
},
});
</script>
<style scoped>
.modalButtonFloatCenter {
position: absolute;
left: 36%;
right: 33%;
white-space: nowrap;
}
</style>
<template>
<b-popover
v-if="valid || validationResults.length === 0 ? false : true"
:disabled="valid || validationResults.length === 0"
over
target="metadataManagerButtonCol"
triggers="hover focus"
placement="top"
>
<template v-slot:title
><b>{{
$parent.$parent.$parent.$t("page.resource.validationErrors")
}}</b></template
>
<div>
<ul>
<li
v-for="validationResult of validationResults"
:key="validationResult.term.value"
>
{{ validationResult.path.value }}
<ul>
<li
v-for="singleMessage of validationResult.message"
:key="singleMessage.value"
>
{{ singleMessage.value }}
</li>
</ul>
</li>
</ul>
</div>
</b-popover>
</template>
<script lang="ts">
import type { ValidationResult } from "rdf-validate-shacl/src/validation-report";
import { defineComponent, PropType } from "vue-demi";
export default defineComponent({
props: {
valid: {
required: true,
type: Boolean,
},
validationResults: {
required: true,
type: Array as PropType<ValidationResult[]>,
},
},
});
</script>
......@@ -13,12 +13,174 @@ export default {
"Das ist die @:page.createResource.title des Coscine UIv2 Apps",
},
resource: {
title: "Resourceseite",
description: "Das ist die @:page.resource.title des Coscine UIv2 Apps",
resources: "Ressourcen",
upload: "Dateien hochladen",
download: "Herunterladen",
edit: "Ressourcenkonfiguration bearbeiten",
info: "Informationen",
canDropFile: "Sie können Ihre Datei hier ablegen!",
loading: "Laden...",
typeToSearch: "Suchen...",
clear: "Leeren",
perPage: "Pro Seite",
more: "Mehr",
fileName: "Name",
lastModified: "Geändert",
actions: "Aktionen",
resourceName: "Ressourcenname",
displayName: "Anzeigename",
description: "Ressourcenbeschreibung",
disciplines: "Disziplin",
keywords: "Ressourcenschlagwörter",
visibility: "Sichtbarkeit",
license: "Lizenz",
usageRights: "Verwendungsrechte",
PID: "Persistente ID",
occupiedBytes: "Belegter Speicher",
noData: "Diese Ressource enthält keine Daten",
emptyTableText: "Diese Ressource enthält keine Dateien.",
emptyFilterText:
"Keine Dateien gefunden die mit Ihrer Anfrage übereinstimmen.",
metadataHeadline: "Metadaten:",
metadataManagerTitleUpload: "Daten hochladen:",
metadataManagerTitleEdit: "Editieren:",
metadataManagerSelectLabel: "Einträge auswählen:",
metadataManagerBadFileName:
"Ungültiger Dateiname. Folgende Zeichen sind nicht zulässig: /:?*<>|",
metadataManagerBtnUpload: "Hochladen",
metadataManagerBtnSelectFiles: "Dateien auswählen",
metadataManagerBtnDownload: "Herunterladen",
metadataManagerBtnReuse: "Wiederverwenden",
metadataManagerBtnMove: "Verschieben",
metadataManagerBtnPublish: "Veröffentlichen",
metadataManagerBtnArchive: "Archivieren",
metadataManagerBtnUpdate: "Aktualisieren",
metadataManagerBtnSaving: "Speichern...",
infoFileType: "Dateiart",
infoFileTypeFolder: "Ordner",
infoFileTypeFile: "Dateien",
infoFileName: "Dateiname",
infoFileAbsolutePath: "Dateipfad",
infoFileLastModified: "Zuletzt geändert",
infoFileCreated: "Erstellt",
infoFileSize: "Dateigröße",
infoFileContent: "Inhalt",
infoFileFiles: "Dateien",
infoFileNoInformation: "Keine Information",
tableIsEmpty:
"Es existieren aktuell noch keine Einträge für diese Ressource.",
metadataManager: "Metadaten Manager",
allFiles: "Alle Dateien",
validationErrors: "Validierungsfehler",
modalSaveDuplicateFilesHeader: "Dateien ersetzen oder überspringen",
modalSaveDuplicateFilesBody:
"Es sind bereits Dateien mit dem gleichen Namen vorhanden. Diese Dateien werden überschrieben:",
modalSaveDuplicateFilesBtnCancel: "HOCHLADEN ABBRECHEN",
modalSaveDuplicateFilesBtnSkip: "DIESE DATEIEN ÜBERSPRINGEN",
modalSaveDuplicateFilesBtnOverwrite: "ÜBERSCHREIBEN",
modalDeleteFolderContentsHeader: "Löschen von Dateien und Metadaten",
modalDeleteFolderContentsBody:
"Sind Sie sicher, dass Sie die folgenen Dateien und Metadaten löschen wollen:",
modalLeavingPageHeader: "Dateien werden hochgeladen",
modalLeavingPageBodyTop: "Diese Dateien werden momentan hochgeladen:",
modalLeavingPageBodyBottom:
"Sind Sie sicher, dass Sie den den Prozess abbrechen wollen?",
modalLeavingPageBtnStay: "AUF SEITE BLEIBEN",
modalLeavingPageBtnLeave: "SEITE VERLASSEN",
toastSavingSuccessfulTitle: "Speichern erfolgreich",
toastSavingSuccessfulBody: "Zahl der erfolgreich gespeicherten Dateien: ",
toastSavingFailedTitle: "Speichern fehlgeschlagen",
toastSavingFailedBodyTop:
"Es ist ein Fehler beim Speichern der folgenden Dateien aufgetreten:",
toastSavingFailedBodyBottom: "Bitte versuchen Sie es erneut.",
dataUrl: "Daten URL",
metadataKey: "Eintragsname",
size: "Dateigröße",
},
settings: {
title: "Settings-Seite",
description: "Das ist die @:page.settings.title des Coscine UIv2 Apps",
},
},
resourceType: {
linked: {
page: {
resource: {
upload: "Einträge speichern",
download: "Öffnen",
noData: "Diese Ressource enthält keine Einträge",
emptyTableText: "Diese Ressource enthält keine Einträge.",
emptyFilterText:
"Keine Einträge gefunden die mit Ihrer Anfrage übereinstimmen.",
metadataManagerTitleUpload: "Einträge speichern:",
metadataManagerSelectLabel: "Einträge auswählen:",
metadataManagerBadFileName:
"Ungültiger Eintrag. Folgende Zeichen sind nicht zulässig: /:?*<>|",
metadataManagerBtnDownload: "Öffnen",
metadataManagerBtnUpload: "Speichern",
metadataManagerBtnSelectFiles: "Neuer Eintrag",
infoFileType: "Eintrag",
infoFileTypeFolder: "Ordner",
infoFileTypeFile: "Einträge",
infoFileName: "Eintragname",
infoFileAbsolutePath: "Eintragpfad",
infoFileSize: "Eintraggröße",
infoFileFiles: "Einträge",
tableIsEmpty:
"Es existieren aktuell noch keine Einträge für diese Ressource.",
allFiles: "Alle Einträge",
modalSaveDuplicateFilesHeader: "Einträge ersetzen oder überspringen",
modalSaveDuplicateFilesBody:
"Es sind bereits Einträge mit dem gleichen Namen vorhanden. Diese Einträge werden überschrieben:",
modalSaveDuplicateFilesBtnCancel: "SPEICHERN ABBRECHEN",
modalSaveDuplicateFilesBtnSkip: "DIESE EINTRÄGE ÜBERSPRINGEN",
modalDeleteFolderContentsHeader:
"Löschen von Einträgen und Metadaten",
modalDeleteFolderContentsBody:
"Sind Sie sicher, dass Sie die folgenen Einträge und Metadaten löschen wollen:",
modalLeavingPageHeader: "Einträge werden hochgeladen",
modalLeavingPageBodyTop:
"Diese Einträge werden momentan hochgeladen:",
toastSavingSuccessfulTitle: "Speichern erfolgreich",
toastSavingSuccessfulBody:
"Zahl der erfolgreich gespeicherten Einträge: ",
toastSavingFailedTitle: "Speichern fehlgeschlagen",
toastSavingFailedBodyTop:
"Es ist ein Fehler beim Speichern der folgenden Einträge aufgetreten:",
},
},
},
} as VueI18n.LocaleMessageObject,
} as VueI18n.LocaleMessageObject;
......@@ -13,12 +13,167 @@ export default {
"This is the @:page.createResource.title for the Coscine UIv2 App",
},
resource: {
title: "Resource Page",
description: "This is the @:page.resource.title for the Coscine UIv2 App",
resources: "Resources",
upload: "Upload Files",
download: "Download",
edit: "Edit Resource Configuration",
info: "Information",
canDropFile: "You can drop your file here!",
loading: "Loading...",
typeToSearch: "Type to search",
clear: "Clear",
perPage: "Per page",
more: "More",
fileName: "Name",
lastModified: "Modified",
actions: "Actions",
resourceName: "Resource Name",
displayName: "Display Name",
description: "Resource Description",
disciplines: "Discipline",
keywords: "Resource Keywords",
visibility: "Visibility",
license: "License",
usageRights: "Usage Rights",
PID: "Persistent ID",
occupiedBytes: "Occupied Storage Space",
noData: "This resource contains no data.",
emptyTableText: "This resource contains no files.",
emptyFilterText: "No files found matching your request.",
metadataHeadline: "Metadata:",
metadataManagerTitleUpload: "Upload Data:",
metadataManagerTitleEdit: "Edit:",
metadataManagerSelectLabel: "Selected Entry(s):",
metadataManagerBadFileName:
"Invalid file name. The following characters are not permissible: /:?*<>|",
metadataManagerBtnUpload: "Upload",
metadataManagerBtnSelectFiles: "Select Files",
metadataManagerBtnDownload: "Download",
metadataManagerBtnReuse: "Reuse",
metadataManagerBtnMove: "Move",
metadataManagerBtnPublish: "Publish",
metadataManagerBtnArchive: "Archive",
metadataManagerBtnUpdate: "Update",
metadataManagerBtnSaving: "Saving...",
infoFileType: "File Type",
infoFileTypeFolder: "Folder",
infoFileTypeFile: "File",
infoFileName: "File name",
infoFileAbsolutePath: "File Path",
infoFileLastModified: "Last modified",
infoFileCreated: "Created",
infoFileSize: "File Size",
infoFileContent: "Content",
infoFileFiles: "Files",
infoFileNoInformation: "No Information",
tableIsEmpty: "There are currently no entities for this resource.",
metadataManager: "Metadata Manager",
allFiles: "All Files",
validationErrors: "Validation Errors",
modalSaveDuplicateFilesHeader: "Replace or skip duplicate files",
modalSaveDuplicateFilesBody:
"One or more files with the same name already exist. Uploading will result in overwriting the following file(s):",
modalSaveDuplicateFilesBtnCancel: "CANCEL UPLOAD",
modalSaveDuplicateFilesBtnSkip: "SKIP DUPLICATE FILES",
modalSaveDuplicateFilesBtnOverwrite: "OVERWRITE",
modalDeleteFolderContentsHeader: "Delete files and metadata",
modalDeleteFolderContentsBody:
"Are you sure, you want to delete the following files and metadata:",
modalLeavingPageHeader: "Upload in progress",
modalLeavingPageBodyTop: "These files are currently uploading:",
modalLeavingPageBodyBottom:
"Are you sure you want to cancel the process?",
modalLeavingPageBtnStay: "STAY ON PAGE",
modalLeavingPageBtnLeave: "LEAVE CURRENT PAGE",
toastSavingSuccessfulTitle: "Saving file(s) successful",
toastSavingSuccessfulBody: "Number of files saved: ",
toastSavingFailedTitle: "Saving file(s) failed",
toastSavingFailedBodyTop:
"An error occured while saving the following files:",
toastSavingFailedBodyBottom: "Please try again.",
dataUrl: "Data URL",
metadataKey: "Entry Name",
size: "File Size",
},
settings: {
title: "Settings Page",
description: "This is the @:page.settings.title for the Coscine UIv2 App",
},
},
resourceType: {
linked: {
page: {
resource: {
upload: "Save Entries",
download: "Open",
noData: "This resource contains no entries.",
emptyTableText: "This resource contains no entries.",
emptyFilterText: "No entries found matching your request.",
metadataManagerTitleUpload: "Save Entry:",
metadataManagerSelectLabel: "Selected Entry(s):",
metadataManagerBadFileName:
"Invalid entry name. The following characters are not permissible: /:?*<>|",
metadataManagerBtnDownload: "Open",
metadataManagerBtnUpload: "Save",
metadataManagerBtnSelectFiles: "New Entry",
infoFileType: "Entry Type",
infoFileTypeFolder: "Folder",
infoFileTypeFile: "Entry",
infoFileName: "Entry name",
infoFileAbsolutePath: "Entry Path",
infoFileSize: "Entry Size",
infoFileFiles: "Entries",
tableIsEmpty: "There are currently no entries for this resource.",
allFiles: "All Entries",
modalSaveDuplicateFilesHeader: "Replace or skip duplicate entries",
modalSaveDuplicateFilesBody:
"One or more entries with the same name already exist. Saving will result in overwriting the following entry(s):",
modalSaveDuplicateFilesBtnCancel: "CANCEL SAVING",
modalSaveDuplicateFilesBtnSkip: "SKIP DUPLICATE ENTRIES",
modalDeleteFolderContentsHeader: "Delete entries and metadata",
modalDeleteFolderContentsBody:
"Are you sure, you want to delete the following entries and metadata:",
modalLeavingPageHeader: "Saving in progress",
modalLeavingPageBodyTop: "These entries are currently saving:",
toastSavingSuccessfulTitle: "Saving entries(s) successful",
toastSavingSuccessfulBody: "Number of entries saved: ",
toastSavingFailedTitle: "Saving entry(s) failed",
toastSavingFailedBodyTop:
"An error occured while saving the following entries:",
},
},
},
} as VueI18n.LocaleMessageObject,
} as VueI18n.LocaleMessageObject;
<template>
<div>
<section
class="container flex flex-col items-center px-5 py-12 mx-auto text-gray-600 body-font md:flex-row"
<div
id="resourcecontentview"
@dragenter="dragEnter"
@dragleave="dragLeave"
@dragend="dragLeave"
@dragover.prevent=""
@drop.prevent="uploadDrop"
>
<div>
<CoscineHeadline :headline="$parent.$t('page.resource.title')" />
<p class="mb-8 leading-relaxed dark:text-white">
{{ $parent.$t("page.resource.description") }}
</p>
<img
alt="From Coscine Old"
src="@/assets/images/Project-Id-R-Guid.png"
<div class="droppable" v-if="showDroppable && fileAddable">
<p class="droppableText">{{ $parent.$t("page.resource.canDropFile") }}</p>
</div>
<coscine-headline
v-show="!isFullscreen"
:headline="$parent.$t('page.resource.resources')"
/>
<b-form-file
ref="fileTrigger"
multiple
@input="fileListUploadSelected"
class="mt-3"
plain
></b-form-file>
<span id="filesViewSpan">
<div id="filesViewCard" :class="isFullscreen == false ? 'card' : ''">
<div :class="isFullscreen == false ? 'card-body' : ''">
<FilesView
ref="filesView"
:folderContents="folderContents"
:currentFolder="currentFolder"
:isUploading="isUploading"
:fileListEdit="fileListEdit"
@showDetail="setShowDetail"
@currentFolder="setCurrentFolder"
@folderContents="setFolder"
@fileListEdit="setFileListEdit"
@clickFileSelect="clickFileSelect"
@waitingForResponse="setWaitingForResponse"
/>
</div>
</div>
</span>
<div
id="metadataManagerDiv"
:class="isMetadataManagerHidden == true ? 'hiddenMetadataManager' : ''"
>
<b-button
v-show="isFullscreen"
squared
id="metadataManagerToggleFullscreen"
@click="toggleMenu()"
><span>{{
$parent.$t("page.resource.metadataManager")
}}</span></b-button
>
<div class="card">
<div class="card-body">
<MetadataManager
:showDetail="showDetail"
:fileListEdit="fileListEdit"
:fileListUpload="fileListUpload"
:folderContents="folderContents"
:currentFolder="currentFolder"
:isUploading="isUploading"
@emptyFileLists="emptyFileLists"
@folderContents="setFolder"
@removeElement="removeElement"
@removeSelection="removeSelection"
@isUploading="setIsUploading"
@clickFileSelect="clickFileSelect"
/>
<div
id="toggleFullscreenButton"
:class="
isMetadataManagerHidden == true ? '' : 'hiddenMetadataManager'
"
>
<button
v-if="isFullscreen"
class="btn btn-secondary"
type="button"
@click="toggleFullscreen"
>
<b-icon icon="fullscreen-exit" />
</button>
<button
v-else
type="button"
class="btn btn-secondary"
@click="toggleFullscreen"
>
<b-icon icon="fullscreen" />
</button>
</div>
</div>
</section>
</div>
</div>
<LoadingSpinner :isWaitingForResponse="isWaitingForResponse" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
import CoscineHeadline from "@/components/CoscineHeadline.vue";
import type Vue from "vue";
// import the store for current module
import { useResourceStore } from "../store";
......@@ -27,6 +109,24 @@ import { useProjectStore } from "@/modules/project/store";
// import the main store
import { useMainStore } from "@/store/index";
import FilesView from "../components/FilesView.vue";
import MetadataManager from "../components/MetadataManager.vue";
import type {
FileInformation,
FolderContent,
FolderInformation,
} from "../utils/EntryDefinition";
import { v4 as uuidv4 } from "uuid";
import type { ProjectObject } from "@coscine/api-client/dist/types/Coscine.Api.Project";
import type {
ResourceObject,
ResourceTypeInformation,
} from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { BFormFile, BTable } from "bootstrap-vue";
export default defineComponent({
setup() {
const mainStore = useMainStore();
......@@ -36,8 +136,381 @@ export default defineComponent({
return { mainStore, resourceStore, projectStore };
},
computed: {
project(): null | ProjectObject {
return this.projectStore.currentProject;
},
resource(): null | ResourceObject {
return this.resourceStore.currentResource;
},
resourceTypeInformation(): null | undefined | ResourceTypeInformation {
if (this.resourceStore.resourceTypes && this.resource) {
return this.resourceStore.resourceTypes.find(
(resourceType) => resourceType.id === this.resource?.type?.id
);
}
return null;
},
fileAddable(): boolean {
return (
!this.resourceTypeInformation?.resourceContent?.readOnly &&
!this.resourceTypeInformation?.resourceContent?.metadataView
?.editableDataUrl
);
},
showDroppable(): boolean {
return this.dragCounter > 0;
},
},
data() {
return {
isWaitingForResponse: false,
fileListEdit: [] as FolderContent[],
showDetail: false,
fileListUpload: [] as FileInformation[],
folderContents: [] as FolderContent[],
currentFolder:
window.location.hash.indexOf("#") !== -1
? window.location.hash.substring(1)
: "/",
dragCounter: 0,
isFullscreen: false,
isMetadataManagerHidden: false,
isUploading: false,
};
},
watch: {
resourceTypeInformation() {
this.emptyFileLists();
},
},
mounted() {
this.$nextTick(() => {
window.addEventListener("resize", this.getWindowWidth);
this.getWindowWidth();
});
this.emptyFileLists();
},
methods: {
clickFileSelect() {
this.showDetail = false;
if (
this.resourceTypeInformation?.resourceContent?.metadataView
?.editableDataUrl
) {
this.emptyFileLists();
} else {
(this.$refs.fileTrigger as BFormFile).$el.dispatchEvent(
new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
})
);
}
},
dragEnter() {
this.dragCounter++;
},
dragLeave() {
this.dragCounter--;
},
emptyFileLists() {
this.removeSelection(0, this.fileListEdit.length);
this.fileListEdit.length = 0;
this.fileListUpload.length = 0;
this.showDetail = false;
this.initializeForResourceType();
},
fileListUploadSelected(selectedFiles: File[] | File) {
if (!Array.isArray(selectedFiles)) {
selectedFiles = [selectedFiles];
}
this.emptyFileLists();
for (const file of selectedFiles) {
this.fileListUpload.push({
id: uuidv4(),
path: this.currentFolder,
version: `${+new Date()}`,
uploading: false,
info: file,
name: file.name,
size: file.size,
lastModified: "" + file.lastModified,
metadata: {},
isFolder: false,
absolutePath: this.currentFolder + file.name,
});
}
(
(this.$refs.filesView as Vue).$refs.adaptTable as BTable
).clearSelected();
this.showDetail = false;
},
initializeForResourceType() {
if (
this.resourceTypeInformation?.resourceContent?.metadataView
?.editableDataUrl
) {
this.fileListUpload.push({
id: uuidv4(),
path: "",
version: `${+new Date()}`,
uploading: false,
name: "",
isFolder: false,
absolutePath: this.currentFolder,
size: 0,
metadata: {},
dataUrl: "",
});
}
},
uploadDrop(ev: DragEvent) {
if (this.fileAddable) {
this.dragCounter = 0;
if (ev?.dataTransfer?.items) {
for (const item of ev.dataTransfer.items) {
if (item.kind === "file") {
const file = item.getAsFile();
if (file !== null) {
this.fileListUploadSelected(file);
}
}
}
}
}
},
setShowDetail(newShowDetail: boolean) {
this.showDetail = newShowDetail;
},
setWaitingForResponse(newIsWaitingForResponse: boolean) {
this.isWaitingForResponse = newIsWaitingForResponse;
},
setIsUploading(newIsUploading: boolean) {
this.isUploading = newIsUploading;
},
setCurrentFolder(newCurrentFolder: string) {
this.currentFolder = newCurrentFolder;
},
setFolder(newFolder: FolderInformation[]) {
this.folderContents = newFolder;
},
setFileListEdit(newFileListEdit: FileInformation[]) {
this.fileListEdit = newFileListEdit;
},
removeElement(index: number, count: number) {
this.fileListUpload.splice(index, count);
},
removeSelection(index: number, count: number) {
const selectionRemovable: FolderContent[] = this.fileListEdit.splice(
index,
count
);
const table = (this.$refs.filesView as Vue).$refs.adaptTable as BTable;
for (let i = 0; i < table.items.length; i++) {
const item = (table.items as FolderContent[])[i];
if (
selectionRemovable.filter((entry) => entry.name === item.name)
.length > 0
) {
table.unselectRow(i);
}
}
},
setFullscreen(newIsFullscreen: boolean) {
this.isFullscreen = newIsFullscreen;
if (newIsFullscreen) {
document.body.classList.add("fullscreen");
this.mainStore.sidebarActive = false;
} else {
document.body.classList.remove("fullscreen");
this.isMetadataManagerHidden = false;
}
},
toggleFullscreen() {
this.setFullscreen(!this.isFullscreen);
},
toggleMenu() {
this.isMetadataManagerHidden = !this.isMetadataManagerHidden;
},
getWindowWidth() {
if (document.documentElement.clientWidth < 1250) {
this.setFullscreen(true);
} else {
this.setFullscreen(false);
}
},
},
components: {
CoscineHeadline,
FilesView,
MetadataManager,
},
});
</script>
<!-- FullScreen + Global Styles -->
<style>
body.fullscreen #resourcecontentview {
position: absolute;
top: 110px;
left: 50px;
right: 0px;
bottom: 0px;
height: auto;
}
body.fullscreen #resourcecontentview .DataSource .headerRow {
margin-left: 0px;
margin-right: 0px;
}
body.fullscreen #metadataManagerDiv {
position: fixed;
bottom: 0px;
top: 110px;
right: 0px;
}
body.fullscreen #metadataManagerDiv .card {
border: 1px solid rgba(0, 0, 0, 0);
height: 100%;
}
body.fullscreen #metadataManagerDiv.hiddenMetadataManager {
right: -600px !important;
}
body.fullscreen #resourcecontentview #filesViewSpan {
margin-right: 25px;
right: 0px;
}
body.fullscreen #toggleFullscreenButton {
left: -68px;
bottom: 4px;
}
#resourcecontentview #filesViewSpan,
body:not(.fullscreen) #resourcecontentview #metadataManagerDiv,
#resourcecontentview .card,
#resourcecontentview .card-body {
height: 100%;
}
#addColumnDropDown button {
padding: 0;
margin: 0;
}
#addColumnDropDown,
#addColumnDropDown__BV_toggle_,
#addColumnDropDown button {
width: 30px;
max-width: 30px;
}
#addColumnDropDown__BV_toggle_ {
min-width: 30px;
}
#addColumnDropDown ul {
padding-left: 10px;
}
#addColumnDropDown .custom-control {
margin-right: 10px;
}
#metadataManagerDiv .input-group button {
border-radius: 0px;
}
#metadataManagerDiv .input-group button:first-child {
border-top-left-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
}
#metadataManagerDiv .input-group button:last-child {
border-top-right-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
}
</style>
<style scoped>
input[type="file"] {
display: none;
font-size: 0px;
position: absolute;
left: 0;
top: 0;
opacity: 0;
}
#resourcecontentview {
position: relative;
height: calc(100vh - 170px);
margin-bottom: 20px;
}
#resourcecontentview >>> #filesViewSpan {
position: absolute;
right: 620px;
left: 0px;
}
#metadataManagerDiv {
position: absolute;
right: 10px;
width: 600px;
background-color: rgb(253, 252, 251);
-webkit-transition: all 0.3s linear;
transition: all 0.3s linear;
}
#metadataManagerToggleFullscreen {
margin-left: -32px;
line-height: 11px;
position: absolute;
top: -3px;
bottom: 0px;
width: 2em;
min-width: 2em;
padding: 0px;
}
#metadataManagerToggleFullscreen >>> span {
display: inline-block;
transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
white-space: nowrap;
margin-left: -54px;
}
#toggleFullscreenButton {
position: absolute;
left: -44px;
bottom: 4px;
background-color: transparent;
-webkit-transition: all 0.3s linear;
-moz-transition: all 0.3s linear;
-ms-transition: all 0.3s linear;
-o-transition: all 0.3s linear;
transition: all 0.3s linear;
}
#toggleFullscreenButton >>> button {
padding: 3px;
min-width: auto;
}
.droppable {
cursor: pointer;
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5); /* Black background with opacity */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
color: white;
vertical-align: middle;
text-align: center;
font-size: 42pt;
}
.droppableText {
margin-top: 9em;
margin-left: 4em;
}
#resourcecontentview >>> .card-body {
padding-top: 8px;
padding-bottom: 8px;
padding-left: 0px;
padding-right: 0px;
}
</style>
import { defineStore } from "pinia";
import { ResourceState } from "./types";
import type {
ApplicationProfile,
ResourceState,
VisitedResourceObject,
} from "./types";
import { StatusCodes } from "http-status-codes";
import { reactive } from "vue-demi";
import { ResourceApi, ResourceTypeApi } from "@coscine/api-client";
import {
BlobApi,
MetadataApi,
ResourceApi,
ResourceTypeApi,
TreeApi,
} from "@coscine/api-client";
import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { Route } from "vue-router/types/router";
import { useLocalStorage } from "@vueuse/core";
import type { BilingualLabels } from "@coscine/api-client/dist/types/Coscine.Api.Metadata";
/*
Store variable name is "this.<id>Store"
......@@ -20,6 +32,7 @@ export const useResourceStore = defineStore({
--------------------------------------------------------------------------------------
*/
state: (): ResourceState => ({
classes: {},
currentId: null,
resourceTypes: null,
visitedResources: {},
......@@ -35,13 +48,29 @@ export const useResourceStore = defineStore({
:label = "this.resourceStore.<getter_name>;
*/
getters: {
currentResource(): ResourceObject | null {
currentFullApplicationProfile(): ApplicationProfile | null {
if (this.currentId) {
return this.visitedResources[this.currentId].fullApplicationProfile;
} else {
return null;
}
},
currentResource(): VisitedResourceObject | null {
if (this.currentId) {
return this.visitedResources[this.currentId];
} else {
return null;
}
},
currentUsedQuota(): number | null {
if (this.currentId) {
return this.visitedResources[this.currentId].usedQuota;
} else {
return null;
}
},
},
/*
--------------------------------------------------------------------------------------
......@@ -64,6 +93,30 @@ export const useResourceStore = defineStore({
}
},
async retrieveApplicationProfile(resource: VisitedResourceObject) {
if (resource.applicationProfile) {
const apiResponse = await MetadataApi.metadataGetProfile(
resource.applicationProfile
);
if (apiResponse.status === StatusCodes.OK) {
resource.fullApplicationProfile = apiResponse.data;
} else {
// Handle other Status Codes
}
}
},
async retrieveUsedQuota(resource: VisitedResourceObject) {
if (resource.id) {
const apiResponse = await BlobApi.blobGetQuota(resource.id);
if (apiResponse.status === StatusCodes.OK) {
resource.usedQuota = Number(apiResponse.data.data.usedSizeByte);
} else {
// Handle other Status Codes
}
}
},
async retrieveResourceTypes() {
const apiResponse =
await ResourceTypeApi.resourceTypeGetEnabledResourceTypes();
......@@ -98,11 +151,135 @@ export const useResourceStore = defineStore({
if (resource && resource.id) {
if (!this.visitedResources[resource.id]) {
// Important! Keep object assignment reactive()
const visitedResource: ResourceObject = reactive(resource);
const visitedResource: VisitedResourceObject = reactive({
...resource,
fullApplicationProfile: null,
usedQuota: null,
storedColumns: useLocalStorage(
`coscine.rcv.storedColumns.${resource.id}`,
null
),
});
this.visitedResources[resource.id] = visitedResource;
}
}
},
async deleteFile(
resource: ResourceObject | null,
absoluteFilePath: string
) {
if (resource && resource.id) {
try {
await BlobApi.blobDeleteFileWithParameter(
resource.id,
absoluteFilePath
);
return true;
} catch {
return false;
}
}
return false;
},
async getClass(className: string): Promise<BilingualLabels> {
if (!this.classes[className]) {
try {
const response = await MetadataApi.metadataGetClassInstances(
className
);
this.classes[className] = response.data;
} catch {
return {};
}
}
return this.classes[className];
},
async getFile(
resource: ResourceObject | null,
absoluteFilePath: string,
asBlob = false
) {
if (resource && resource.id) {
try {
const response = await BlobApi.blobGetFileWithParameter(
resource.id,
absoluteFilePath,
asBlob
? {
responseType: "blob",
}
: undefined
);
return response.data;
} catch {
return null;
}
}
return null;
},
async getMetadata(
resource: ResourceObject | null,
absoluteFilePath: string
) {
if (resource && resource.id) {
try {
const response = await TreeApi.treeGetMetadataWithParameter(
resource.id,
absoluteFilePath
);
return response.data;
} catch {
return null;
}
}
return null;
},
async storeFile(
resource: ResourceObject | null,
absoluteFilePath: string,
files: Blob[],
options?: unknown
) {
if (resource && resource.id) {
try {
await BlobApi.blobUploadFileWithParameter(
resource.id,
absoluteFilePath,
files,
options
);
return true;
} catch {
return false;
}
}
return false;
},
async storeMetadata(
resource: ResourceObject | null,
absoluteFilePath: string,
body: unknown
) {
if (resource && resource.id) {
try {
await TreeApi.treeStoreMetadataForFileWithParameter(
resource.id,
absoluteFilePath,
{ data: body }
);
return true;
} catch {
return false;
}
}
return false;
},
},
});
......