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

Target

Select target project
  • coscine/frontend/apps/ui
1 result
Select Git revision
Show changes
Commits on Source (28)
Showing
with 381 additions and 215 deletions
......@@ -12,5 +12,6 @@
"eslint.nodePath": ".yarn/sdks",
"prettier.prettierPath": ".yarn/sdks/prettier/index.js",
"typescript.tsdk": ".yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
"typescript.enablePromptUseWorkspaceTsdk": true,
"vue3snippets.enable-compile-vue-file-on-did-save-code": false
}
{
"name": "ui",
"version": "1.21.0",
"version": "1.22.0",
"private": true,
"scripts": {
"dev": "vite",
......@@ -14,7 +14,7 @@
},
"dependencies": {
"@coscine/api-client": "^2.9.0",
"@coscine/form-generator": "^3.0.12",
"@coscine/form-generator": "^3.1.0",
"@rdfjs-elements/formats-pretty": "^0.4.3",
"@rdfjs/data-model": "^2.0.0",
"@rdfjs/dataset": "^2.0.0",
......@@ -100,7 +100,7 @@
"vitest": "^0.24.3",
"vue-template-compiler": "^2.7.10"
},
"packageManager": "yarn@3.3.0",
"packageManager": "yarn@3.3.1",
"resolutions": {
"readable-stream": "3.6.0"
}
......
......@@ -53,19 +53,20 @@
<script lang="ts">
import { defineComponent, type PropType } from "vue";
import type { TranslateResult } from "vue-i18n";
import type { RawLocation } from "vue-router";
export default defineComponent({
components: {},
props: {
title: {
type: String,
type: [String, Object] as PropType<
string | TranslateResult | null | undefined
>,
required: true,
},
badgeText: {
default: "",
type: String,
type: [String, Object] as PropType<string | TranslateResult>,
},
badgeVisibility: {
default: false,
......@@ -82,7 +83,7 @@ export default defineComponent({
},
toSettings: {
default: null,
type: Object as PropType<RawLocation>,
type: Object as PropType<RawLocation | null>,
},
to: {
type: Object as PropType<RawLocation>,
......
......@@ -3,18 +3,19 @@
</template>
<script lang="ts">
export default {
import { defineComponent, type PropType } from "vue";
import type { TranslateResult } from "vue-i18n";
export default defineComponent({
props: {
headline: {
default: "",
type: String,
type: [String, Object] as PropType<string | TranslateResult>,
},
h: {
default: "h4",
type: String,
},
},
};
});
</script>
<style scoped></style>
......@@ -9,10 +9,7 @@ export const AdminRoutes: RouteConfig[] = [
{
path: "/admin",
component: AdminModule,
// only authenticated users can access admin
meta: {
requiresAdmin: true,
requiresAuth: true,
i18n: AdminI18nMessages,
},
children: [
......@@ -20,8 +17,12 @@ export const AdminRoutes: RouteConfig[] = [
path: "/",
name: "admin",
component: Admin,
// only authenticated users can access admin
meta: {
breadCrumb: "admin",
// TODO: Implement Admin Check
requiresAdmin: true,
requiresAuth: true,
},
},
],
......
......@@ -5,36 +5,10 @@
{{ $t("page.logout.title") }}
</b-card-title>
<!-- Buttons -->
<!-- Logout Message & Login Button -->
<div class="v_gapped_container">
<!-- ORCiD Logout Button -->
<b-button
v-if="isLoggedInWithOrcid"
variant="primary"
@click.prevent="logOutFromOrcid"
>
<b-img
class="d-inline mr-1"
alt="ORCID logo"
src="https://info.orcid.org/wp-content/uploads/2019/11/orcid_24x24.png"
/>
<span>{{ $t("page.logout.button_orcid") }}</span>
</b-button>
<!-- Shibboleth Logout Button -->
<b-button
v-if="isLoggedInWithShibboleth"
variant="primary"
@click="logOutFromShibboleth"
>
{{ $t("page.logout.button_shibboleth") }}
</b-button>
<!-- Logout Success -->
<b-card-body
v-if="!isLoggedInWithOrcid && !isLoggedInWithShibboleth"
class="h6 text-primary text-center"
>
<b-card-body v-if="isLoggedOut" class="h6 text-primary text-center">
{{ $t("page.logout.success") }}
</b-card-body>
......@@ -48,7 +22,6 @@
<script lang="ts">
import { defineComponent } from "vue";
import type { DFNAAIInstitution } from "../types";
import "@/plugins/deprecated/vue-multiselect";
// import the store for current module
......@@ -63,41 +36,17 @@ export default defineComponent({
return { loginStore };
},
data() {
return {
isLoggedInWithOrcid: null as boolean | null,
};
},
computed: {
isLoggedInWithShibboleth(): boolean | null {
const query = this.$route.query["loggedInWithShibboleth"];
isLoggedOut(): boolean | null {
const query = this.$route.query["logout"];
if (query) {
return Boolean(JSON.parse(query as string));
}
return null;
},
selectedInstitution(): DFNAAIInstitution | null {
return this.loginStore.selectedInstitution;
},
},
async created() {
this.isLoggedInWithOrcid = await this.loginStore.getOrcidLoginStatus();
},
methods: {
async logOutFromOrcid() {
// Set the parameter logUserOut = true
await this.loginStore.getOrcidLoginStatus(true);
},
logOutFromShibboleth() {
if (this.selectedInstitution) {
this.loginStore.logoutFromShibboleth(this.selectedInstitution);
}
},
logBackIn() {
this.$router.push({ name: "login" });
},
......
......@@ -41,8 +41,6 @@ export default {
title: "Ausloggen",
success: "Sie wurden erfolgreich ausgeloggt",
log_in: "Wiederholt einloggen",
button_orcid: "Von ORCiD ausloggen",
button_shibboleth: "Von Shibboleth ausloggen",
},
tos: {
......
......@@ -41,8 +41,6 @@ export default {
title: "Logout",
success: "You have been successfully logged out",
log_in: "Log back in",
button_orcid: "Logout from ORCiD",
button_shibboleth: "Logout from Shibboleth",
},
tos: {
......
<template>
<div>
<b-row>
<b-col>
<b-row align-h="between">
<!-- Resources -->
<b-col id="resources">
......@@ -17,7 +19,10 @@
@open-card="openCreateResource($event)"
/>
<b-tooltip target="addResource">
<i18n v-if="!isEmailValid" path="page.project.tooltipDisabled">
<i18n
v-if="!isEmailValid"
path="page.project.tooltipDisabled"
>
<template #linkToUserProfile>
<router-link
:to="{ name: 'userprofile' }"
......@@ -53,15 +58,10 @@
</b-card-group>
</div>
</b-col>
<!-- Members -->
<b-col id="members">
<MembersList v-if="project" />
</b-col>
</b-row>
<b-row align-h="between">
<!-- Sub-Projects -->
<div id="sub-projects">
<b-col id="sub-projects">
<CoscineHeadline :headline="$tc('page.project.subProject', 0)" />
<div class="list">
......@@ -92,7 +92,15 @@
/>
</b-card-group>
</div>
</div>
</b-col>
</b-row>
</b-col>
<!-- Members -->
<b-col id="members">
<MembersList v-if="project" />
</b-col>
</b-row>
</div>
</template>
......@@ -156,6 +164,9 @@ export default defineComponent({
return false;
}
},
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
user(): UserObject | null {
return this.userStore.user;
},
......@@ -203,12 +214,12 @@ export default defineComponent({
} as RawLocation;
return route;
},
toResourceSettings(resource: ResourceObject): RawLocation {
toResourceSettings(resource: ResourceObject): RawLocation | null {
const route = {
name: "resource-settings",
params: { guid: resource.id },
} as RawLocation;
return route;
return !this.isGuest || this.isResourceCreator(resource) ? route : null;
},
openCreateProject(to: RawLocation) {
this.$router.push(to);
......@@ -253,6 +264,13 @@ export default defineComponent({
);
}
},
isResourceCreator(resource: ResourceObject): boolean | undefined {
if (resource && resource.creator && this.user && this.user.id) {
return resource.creator === this.user.id;
} else {
return undefined;
}
},
},
});
</script>
......
......@@ -187,6 +187,20 @@ export const useProjectStore = defineStore({
return undefined;
}
},
currentUserRoleIsMember(): boolean | undefined {
if (this.currentUserRole) {
return this.currentUserRole.displayName === "Member";
} else {
return undefined;
}
},
currentUserRoleIsGuest(): boolean | undefined {
if (this.currentUserRole) {
return this.currentUserRole.displayName === "Guest";
} else {
return undefined;
}
},
},
/*
--------------------------------------------------------------------------------------
......
<template>
<div>
<RouterView v-if="moduleIsReady" />
<b-row v-else align-h="center" class="my-4">
<b-spinner variant="primary" />
</b-row>
</div>
</template>
......@@ -43,7 +46,10 @@ export default defineComponent({
return null;
},
moduleIsReady(): boolean {
if (this.projectStore.currentUserRole) {
return true;
}
return false;
},
},
......
......@@ -214,7 +214,7 @@
text-field="displayName"
value-field="id"
:state="
v$.resourceForm.license.$dirty
v$.resourceForm.license.$dirty && resourceForm.license
? !v$.resourceForm.license.$error
: null
"
......@@ -223,7 +223,7 @@
@change="setLicense(selectedLicense)"
>
<template #first>
<option :value="null" disabled>
<option :value="null">
{{ $t("form.resource.resourceLicenseSelect") }}
</option>
</template>
......@@ -486,6 +486,8 @@ export default defineComponent({
) as LicenseObject;
this.resourceForm.license = license;
this.v$.resourceForm.license?.$touch();
} else if (!id) {
this.resourceForm.license = null;
}
},
......
......@@ -49,12 +49,13 @@
<div class="invalid-tooltip">
{{ $t("resourceType.gitlab.accessTokenInvalidTooltip") }}
</div>
<template #popover>
{{ $t("resourceType.gitlab.accessTokenInfoPopover") }}
<b-link
:href="$t('resourceType.gitlab.accessTokenInfoPopoverUrl').toString()"
target="_blank"
>
{{ $t("resourceType.gitlab.accessTokenInfoPopover") }}
>{{ $t("default.help") }}
</b-link>
</template>
</CoscineFormGroup>
......@@ -174,9 +175,13 @@ import type {
import type { GitlabInformation } from "@/modules/resource/types";
import { useVuelidate, type ValidationArgs } from "@vuelidate/core";
import { required, url } from "@vuelidate/validators";
import { and, helpers, required, url } from "@vuelidate/validators";
import { isNumber } from "lodash";
const isHttpsUrl = (value: string) =>
!helpers.req(value) || value.startsWith("https://");
const isValidGitLabUrl = and(url, isHttpsUrl);
export default defineComponent({
props: {
value: {
......@@ -218,7 +223,7 @@ export default defineComponent({
validations() {
return {
gitlabInformation: {
domain: { required, url },
domain: { required, isValidGitLabUrl },
accessToken: { required },
project: { required },
reference: { required },
......
......@@ -45,6 +45,9 @@
<template #head(lastModified)="row">
<span>{{ row.label }}</span>
</template>
<template #head(size)="row">
<span>{{ row.label }}</span>
</template>
<template #head()="row">
<template v-if="visibleColumns.includes(row.field.key)">
<span>{{ row.label }}</span>
......@@ -107,37 +110,33 @@
@click="
row.item.isFolder ? openFolder(row.item) : openFile(row.item)
"
>{{
$t("page.resource.metadataManagerBtnDownload")
}}</b-dropdown-item
>
{{ $t("page.resource.metadataManagerBtnDownload") }}
</b-dropdown-item>
<b-dropdown-item
v-if="!isGuest || isResourceCreator"
:disabled="
(resource && resource.archived) ||
(resourceTypeInformation && !resourceTypeInformation.canDelete)
"
@click="showModalDeleteFile(row.item)"
>{{ $t("buttons.delete") }}
>
{{ $t("buttons.delete") }}
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(size)="row">
{{ renderSize(row.item) }}
</template>
<template #cell(lastModified)="row">
{{ renderDate(row.item) }}
</template>
</b-table>
</b-row>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, reactive } from "vue";
import { defineComponent, type PropType, reactive } from "vue";
// import the store for current module
import useResourceStore from "../../store";
import useProjectStore from "@/modules/project/store";
import useUserStore from "@/modules/user/store";
import FilesViewHeader from "./FilesViewHeader.vue";
......@@ -160,7 +159,9 @@ import { FileUtil } from "../../utils/FileUtil";
import { v4 as uuidv4 } from "uuid";
import { parseRDFDefinition } from "../../utils/linkedData";
import factory from "rdf-ext";
import type { Dataset, Literal, Quad } from "@rdfjs/types";
import type { Dataset, Literal } from "@rdfjs/types";
import type { BilingualLabels } from "@coscine/api-client/dist/types/Coscine.Api.Metadata";
import type { UserObject } from "@coscine/api-client/dist/types/Coscine.Api.User";
interface CustomTableField extends BvTableField {
key: string;
......@@ -193,8 +194,9 @@ export default defineComponent({
setup() {
const resourceStore = useResourceStore();
const projectStore = useProjectStore();
const userStore = useUserStore();
return { resourceStore, projectStore };
return { resourceStore, projectStore, userStore };
},
data() {
return {
......@@ -208,6 +210,19 @@ export default defineComponent({
},
computed: {
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
isResourceCreator(): boolean | undefined {
if (this.resource && this.resource.creator && this.user && this.user.id) {
return this.resource.creator === this.user.id;
} else {
return undefined;
}
},
user(): UserObject | null {
return this.userStore.user;
},
applicationProfile(): Dataset | null {
return this.resourceStore.currentFullApplicationProfile;
},
......@@ -215,6 +230,9 @@ export default defineComponent({
return this.resourceStore.currentResource;
},
classes(): { [className: string]: BilingualLabels } {
return this.resourceStore.classes;
},
resourceTypeInformation(): null | undefined | ResourceTypeInformation {
if (this.resourceStore.resourceTypes && this.resource) {
return this.resourceStore.resourceTypes.find(
......@@ -233,7 +251,6 @@ export default defineComponent({
//Define as computed property to translate RCV Table
return this.$root.$i18n.locale;
},
defaultHeaders(): Array<CustomTableField> {
// Define as computed property to have table
// header text react on language changes.
......@@ -249,16 +266,23 @@ export default defineComponent({
key: "lastModified",
sortable: true,
active: true,
formatter: (value, key, item: FolderContent) => {
return this.renderDate(item)
},
filterByFormatted: true,
},
{
label: this.$t("page.resource.size").toString(),
key: "size",
sortable: true,
active: true,
formatter: (value, key, item: FolderContent) => {
return this.renderSize(item);
},
filterByFormatted: true,
},
];
},
filterFields(): string[] {
const filterFields = this.defaultHeaders.map((header) => header.key);
filterFields.push(
......@@ -305,6 +329,7 @@ export default defineComponent({
return visibleColumns;
},
},
watch: {
applicationProfile() {
this.getColumns();
......@@ -370,12 +395,44 @@ export default defineComponent({
const metadata = item.metadata;
const entries = metadata.match(undefined, path.object);
if (entries.size) {
return Array.from(entries)
.map((entry: Quad) => entry.object.value)
.join("<br>");
const returnList: string[] = [];
for (const entry of entries) {
const entryObject = entry.object;
let entryValue = entryObject.value;
if (entryObject.termType === "Literal") {
if (entryObject.datatype.value.endsWith("date")) {
const date = entryObject.value;
const dateObject = new Date(date);
entryValue = dateObject.toLocaleDateString(
this.$i18n.locale
);
}
} else if (entryObject.termType === "NamedNode") {
for (const classValue of Object.values(this.classes)) {
const langClassList =
this.$i18n.locale === "de"
? classValue.de
: classValue.en;
if (langClassList) {
const foundEntry = langClassList.find(
(langClassEntry) =>
langClassEntry.value === entryValue
);
if (foundEntry && foundEntry.name) {
entryValue = foundEntry.name;
break;
}
}
}
}
returnList.push(entryValue);
}
return returnList.join("<br>");
}
return "";
},
sortByFormatted: true,
filterByFormatted: true,
})
);
}
......@@ -620,7 +677,7 @@ export default defineComponent({
}
},
renderDate(item: FolderContent): string {
if (item.lastModified === null || item.lastModified === undefined) {
if (!item.lastModified) {
return "";
}
const date = item.lastModified;
......@@ -643,46 +700,55 @@ export default defineComponent({
position: relative;
margin-left: 5px;
}
#resourceViewTable thead th:first-of-type div label {
cursor: pointer;
}
#resourceViewTable thead th:last-of-type {
text-align: center;
}
#resourceViewTable td,
#resourceViewTable th {
vertical-align: middle;
cursor: initial;
white-space: nowrap;
}
#resourceViewTable td,
#resourceViewTable tr td:not(:first-child):not(:last-child),
#resourceViewTable tr th:not(:first-child):not(:last-child) {
position: relative;
}
#resourceViewTable td a {
padding-left: 14px;
padding-right: 30px;
vertical-align: middle;
}
#resourceViewTable tr td:nth-child(2),
#resourceViewTable tr th:nth-child(2) {
max-width: 170px !important;
min-width: 170px !important;
width: 170px !important;
}
#resourceViewTable tr td:last-child,
#resourceViewTable tr th:last-child {
max-width: 55px !important;
min-width: 55px !important;
width: 55px !important;
}
#resourceViewTable tr td:not(:first-child):not(:last-child),
#resourceViewTable tr th:not(:first-child):not(:last-child) {
max-width: 200px;
text-overflow: ellipsis;
overflow: hidden;
}
#resourceViewTable i,
#resourceViewTable input,
#resourceViewTable div.tableCheck.custom-checkbox label,
......@@ -690,15 +756,18 @@ export default defineComponent({
vertical-align: top;
cursor: pointer;
}
#resourceViewTable tr:hover .dotMenu button {
font-weight: bold;
margin: 0;
}
#resourceViewTable .dotMenu {
position: absolute;
right: 0px;
margin-top: -5px;
}
#resourceViewTable .dotMenu .dropdown-item {
margin: 1px;
}
......@@ -709,27 +778,33 @@ export default defineComponent({
#resourceViewTable {
overflow: visible;
}
#resourceViewTable :deep(.btn-link) {
padding-left: 5px !important;
padding-right: 5px !important;
background: none !important;
min-width: auto;
}
#resourceViewTable th:last-of-type,
.center-align {
text-align: center;
}
#resourceViewTable th > i {
position: absolute;
right: 10px;
top: 8px;
}
#resourceViewTable th .additionalColumnHeader {
margin-right: 20px;
}
#resourceViewTable th .additionalColumnHeader svg {
cursor: pointer;
}
.adaptTable {
overflow: auto;
position: absolute;
......@@ -739,16 +814,20 @@ export default defineComponent({
right: 10px;
width: auto;
}
.rightFloating {
float: right;
}
.dataSourceItem {
vertical-align: sub;
}
.DataSource {
height: inherit;
margin-top: 7px;
}
.tableCheck {
text-align: center;
margin-right: -0.5em;
......@@ -757,15 +836,18 @@ export default defineComponent({
left: 17px;
cursor: pointer;
}
#resourceViewTable .tableCheck,
#resourceViewTable .dotMenu {
visibility: hidden;
}
#resourceViewTable tr:hover .tableCheck,
#resourceViewTable tr:hover .dotMenu,
#resourceViewTable .b-table-row-selected .tableCheck {
visibility: visible;
}
.leftButton {
height: calc(1.4em + 0.75rem + 2px);
}
......
......@@ -16,7 +16,7 @@
<!-- Resource Settings Button -->
<b-button
v-if="canEditResource"
v-if="!isGuest || isResourceCreator"
:title="$t('page.resource.edit')"
size="sm"
class="btn-sm mx-1"
......@@ -27,6 +27,7 @@
<!-- Upload Button -->
<b-button
v-if="!isGuest || isResourceCreator"
:title="$t('page.resource.upload')"
size="sm"
class="btn-sm mx-1"
......@@ -221,6 +222,16 @@ export default defineComponent({
isOwner(): boolean | undefined {
return this.projectStore.currentUserRoleIsOwner;
},
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
isResourceCreator(): boolean | undefined {
if (this.resource && this.resource.creator && this.user && this.user.id) {
return this.resource.creator === this.user.id;
} else {
return undefined;
}
},
project(): null | ProjectObject {
return this.projectStore.currentProject;
},
......@@ -241,13 +252,6 @@ export default defineComponent({
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;
},
......@@ -272,6 +276,17 @@ export default defineComponent({
},
},
async created() {
// ToDo: May not always work right away on direct URL page load
if (this.project && this.resource && !this.isGuest) {
// Load Quotas for the project if not present - needed for the quota progress bar
if (this.projectStore.currentQuotas === null) {
await this.projectStore.retrieveQuotas(this.project);
await this.resourceStore.retrieveUsedQuota(this.resource);
}
}
},
methods: {
async getGitlabProjectName() {
this.gitlabProjects = await this.resourceStore.getGitlabAllProjects(
......
......@@ -64,7 +64,9 @@
:locale="$root.$i18n.locale"
:selected-shape="resource.applicationProfile"
:shapes="applicationProfile"
:disabled-mode="resource.archived"
:disabled-mode="
(isGuest && !isResourceCreator) || resource.archived
"
:validation-context="currentFileId + ''"
:class-receiver="receiveClass"
:user-receiver="async () => user"
......@@ -226,6 +228,16 @@ export default defineComponent({
};
},
computed: {
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
isResourceCreator(): boolean | undefined {
if (this.resource && this.resource.creator && this.user && this.user.id) {
return this.resource.creator === this.user.id;
} else {
return undefined;
}
},
applicationProfile(): Dataset | null {
return this.resourceStore.currentFullApplicationProfile;
},
......@@ -243,7 +255,6 @@ export default defineComponent({
}
return null;
},
editableDataUrl(): boolean {
return (
this.resourceTypeInformation?.resourceContent?.metadataView
......@@ -341,6 +352,7 @@ export default defineComponent({
return this.validationResults.slice(1).every((entry) => entry.conforms);
},
},
watch: {
currentMetadata() {
this.currentUsedMetadata = this.currentMetadata;
......
<template>
<b-row id="metadataManagerButtonRowBottom">
<span v-if="isUploading" class="processStatement"
>{{
<span v-if="isUploading" class="processStatement">
{{
totalNumberOfCurrentlyProcessedFiles - numberOfCurrentlyProcessedFiles
}}/{{ totalNumberOfCurrentlyProcessedFiles }}</span
>
}}/{{ totalNumberOfCurrentlyProcessedFiles }}
</span>
<div
id="metadataManagerButtonRowBottomContainer"
:class="saveButtonDisabled ? 'buttondisabled' : ''"
>
<!-- Upload Progress Bar -->
<b-col>
<b-progress
v-if="isUploading"
......@@ -17,10 +18,13 @@
max="100"
show-progress
animated
></b-progress>
/>
</b-col>
<!-- Upload Button -->
<b-col id="metadataManagerButtonCol">
<b-button
v-if="!isGuest || isResourceCreator"
id="metadataManagerButtonRowBottomSave"
class="metadataManagerButtonRowBottomSave"
variant="primary"
......@@ -32,15 +36,16 @@
? $emit('uploadPreparation')
: $emit('update')
"
><b-spinner v-show="isUploading" label="Spinning"></b-spinner
>{{
>
<b-spinner v-show="isUploading" label="Spinning" />
{{
isUploading
? $t("page.resource.metadataManagerBtnSaving")
: !showDetail
? $t("page.resource.metadataManagerBtnUpload")
: $t("page.resource.metadataManagerBtnUpdate")
}}</b-button
>
}}
</b-button>
</b-col>
</div>
</b-row>
......@@ -48,6 +53,12 @@
<script lang="ts">
import { defineComponent } from "vue";
import useProjectStore from "@/modules/project/store";
import useResourceStore from "@/modules/resource/store";
import useUserStore from "@/modules/user/store";
import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { UserObject } from "@coscine/api-client/dist/types/Coscine.Api.User";
export default defineComponent({
props: {
......@@ -76,6 +87,32 @@ export default defineComponent({
type: Number,
},
},
setup() {
const projectStore = useProjectStore();
const resourceStore = useResourceStore();
const userStore = useUserStore();
return { projectStore, resourceStore, userStore };
},
computed: {
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
isResourceCreator(): boolean | undefined {
if (this.resource && this.resource.creator && this.user && this.user.id) {
return this.resource.creator === this.user.id;
} else {
return undefined;
}
},
resource(): ResourceObject | null {
return this.resourceStore.currentResource;
},
user(): UserObject | null {
return this.userStore.user;
},
},
});
</script>
......
<template>
<b-row id="metadataManagerButtonRowTop" align-h="between">
<b-col>
<!-- Select Files Button -->
<b-button
v-if="!isGuest || isResourceCreator"
id="buttonSelectFiles"
variant="secondary"
:placeholder="$t('page.resource.metadataManagerBtnSelectFiles')"
:disabled="isUploading || readOnly || (resource && resource.archived)"
autofocus
@click="$emit('selectFiles')"
>{{ $t("page.resource.metadataManagerBtnSelectFiles") }}
>
{{ $t("page.resource.metadataManagerBtnSelectFiles") }}
</b-button>
</b-col>
<b-col>
<!-- Input Group with Download button -->
<b-input-group id="metadataManagerDropDownMenu" class="float-right">
<b-dropdown
v-if="!isGuest || isResourceCreator"
id="addColumnDropDown"
size="sm"
right
......@@ -25,20 +31,22 @@
"
>
<b-dropdown-item
v-if="showDetail"
v-if="showDetail && (!isGuest || isResourceCreator)"
:disabled="
resourceTypeInformation && !resourceTypeInformation.canDelete
"
@click="$emit('showModalDeleteFolderContents')"
>{{ $t("buttons.delete") }}</b-dropdown-item
>
{{ $t("buttons.delete") }}
</b-dropdown-item>
</b-dropdown>
<b-button
v-if="!editableDataUrl"
:disabled="!showDetail || shownFiles.length === 0"
@click="$emit('download')"
>{{ $t("page.resource.metadataManagerBtnDownload") }}</b-button
>
{{ $t("page.resource.metadataManagerBtnDownload") }}
</b-button>
</b-input-group>
</b-col>
</b-row>
......@@ -47,6 +55,8 @@
<script lang="ts">
import { defineComponent, type PropType } from "vue";
import useProjectStore from "@/modules/project/store";
import useUserStore from "@/modules/user/store";
// import the store for current module
import useResourceStore from "../../../store";
......@@ -54,6 +64,7 @@ import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.
import type { FolderContent } from "../../../utils/EntryDefinition";
import type { ResourceTypeInformation } from "@coscine/api-client/dist/types/Coscine.Api.Resources";
import type { UserObject } from "@coscine/api-client/dist/types/Coscine.Api.User";
export default defineComponent({
props: {
editableDataUrl: {
......@@ -82,11 +93,26 @@ export default defineComponent({
},
},
setup() {
const projectStore = useProjectStore();
const resourceStore = useResourceStore();
const userStore = useUserStore();
return { resourceStore };
return { projectStore, resourceStore, userStore };
},
computed: {
isGuest(): boolean | undefined {
return this.projectStore.currentUserRoleIsGuest;
},
isResourceCreator(): boolean | undefined {
if (this.resource && this.resource.creator && this.user && this.user.id) {
return this.resource.creator === this.user.id;
} else {
return undefined;
}
},
user(): UserObject | null {
return this.userStore.user;
},
resourceTypeInformation(): null | undefined | ResourceTypeInformation {
if (this.resourceStore.resourceTypes && this.resource) {
return this.resourceStore.resourceTypes.find(
......
......@@ -14,7 +14,7 @@
:disabled="!isUserAllowedToEdit"
switch
size="lg"
@click.prevent="isArchiveModalVisible = true"
@change="isArchiveModalVisible = true"
/>
</CoscineFormGroup>
......@@ -34,7 +34,7 @@
!isUserAllowedToEdit ||
(resourceTypeInformation && !resourceTypeInformation.canDelete)
"
@click.prevent="isDeleteModalVisible = true"
@change="isDeleteModalVisible = true"
>
{{ $t("buttons.delete") }}
</b-button>
......
......@@ -77,11 +77,11 @@
{{ $t("resourceType.gitlab.accessTokenInvalidTooltip") }}
</div>
<template #popover>
{{ $t("resourceType.gitlab.accessTokenInfoPopover") }}
<b-link
:href="$t('resourceType.gitlab.accessTokenInfoPopoverUrl').toString()"
target="_blank"
>
{{ $t("resourceType.gitlab.accessTokenInfoPopover") }}
>{{ $t("default.help") }}
</b-link>
</template>
</CoscineFormGroup>
......