Skip to content

Commit

Permalink
Merge branch 'main' into BXC-4356-update-matomo-client
Browse files Browse the repository at this point in the history
  • Loading branch information
Sharon Luong committed Jan 23, 2024
2 parents fc12c45 + 8d0ea58 commit 7561f6c
Show file tree
Hide file tree
Showing 22 changed files with 1,114 additions and 43 deletions.
16 changes: 16 additions & 0 deletions static/css/sass/cdr_ui_styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,14 @@ table.dataTable {
border-radius: 5px;
}

.is-narrow.item-actions {
text-align: right;

.actionlink {
margin-bottom: 0;
}
}

.item-actions {
.actionlink {
a.action {
Expand Down Expand Up @@ -1038,6 +1046,14 @@ table.dataTable {
}
}

.is-narrow.item-actions {
text-align: left;

.actionlink {
margin-bottom: 3px;
}
}

.record-metadata {
justify-content: center;
display: grid;
Expand Down
8 changes: 4 additions & 4 deletions static/js/admin/vue-permissions-editor/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion static/js/admin/vue-permissions-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
"jest-environment-jsdom": "^29.7.0",
"moxios": "^0.4.0",
"sass": "^1.69.7",
"vite": "4.5.1"
"vite": "4.5.2"
}
}
8 changes: 4 additions & 4 deletions static/js/vue-cdr-access/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion static/js/vue-cdr-access/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@
"moxios": "^0.4.0",
"pretty": "^2.0.0",
"sass": "^1.69.7",
"vite": "4.5.1"
"vite": "4.5.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,31 @@
<div v-if="hasPermission(recordData, 'editDescription')" class="actionlink">
<a class="edit button action" :href="editDescriptionUrl(recordData.briefObject.id)"><i class="fa fa-edit"></i> {{ $t('full_record.edit') }}</a>
</div>
<template v-if="recordData.resourceType === 'File' && hasDownloadAccess(recordData)">
<div class="header-button" v-html="downloadButtonHtml(recordData.briefObject)"></div>
<div class="actionlink" v-if="hasPermission(recordData, 'viewOriginal')">
<a class="button view action" :href="recordData.dataFileUrl">
<i class="fa fa-search" aria-hidden="true"></i> View</a>
</div>
<template v-if="recordData.resourceType === 'File'">
<template v-if="hasDownloadAccess(recordData)">
<div class="header-button" v-html="downloadButtonHtml(recordData.briefObject)"></div>
<div class="actionlink" v-if="hasPermission(recordData, 'viewOriginal')">
<a class="button view action" :href="recordData.dataFileUrl">
<i class="fa fa-search" aria-hidden="true"></i> View</a>
</div>
</template>
<template v-if="hasPermission(recordData, 'viewHidden')">
<single-use-link :uuid="recordData.briefObject.id"></single-use-link>
</template>
</template>
</div>
</template>

<script>
import singleUseLink from '@/components/full_record/singleUseLink.vue';
import fileDownloadUtils from '../../mixins/fileDownloadUtils';
import fullRecordUtils from '../../mixins/fullRecordUtils';
export default {
name: 'restrictedContent',
components: {singleUseLink},
mixins: [fileDownloadUtils, fullRecordUtils],
props: {
Expand Down
162 changes: 162 additions & 0 deletions static/js/vue-cdr-access/src/components/full_record/singleUseLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<template>
<div class="header-button-single-download">
<div class="actionlink single-download">
<div class="single-use-msg-text" :class="{'display-msg': this.message !== ''}">
{{ this.message }}
</div>
<a class="button action" id="single-use-link" href="#" @click.prevent="createLink()">{{ $t('full_record.download_single_use') }}</a>
<ul>
<li v-for="single_use_link in single_use_links">
<div class="download-link-wrapper">
<div>{{ $t('full_record.created_link', { link: single_use_link.accessCode, expire_time: single_use_link.expires }) }}</div>
<a @click.prevent="copyUrl(single_use_link.link)" href="#" class="download button action">Copy Link</a>
</div>
</li>
</ul>
</div>
</div>
</template>

<script>
import axios from 'axios';
import {formatDistanceToNow} from "date-fns";
import {toDate} from "date-fns";
export default {
name: 'singleUseLink',
props: {
uuid: String
},
watch: {
'$route.path': {
handler() {
this.single_use_links = []
}
}
},
data() {
return {
single_use_links: [],
message: ''
}
},
methods: {
createLink() {
axios({
method: 'post',
url: `/services/api/single_use_link/create/${this.uuid}`
}).then((response) => {
let basePath = window.location.hostname;
let accessCode = response.data.key;
this.single_use_links.push({"link": this.generateUrl(basePath, accessCode),
"accessCode": accessCode.substring(0, 8),
"expires": this.formatTimestamp(response.data.expires)
});
}).catch((error) => {
console.log(error);
this.message = this.$t('full_record.created_link_failed', { uuid: this.uuid});
this.fadeOutMsg();
});
},
async copyUrl(text) {
try {
await navigator.clipboard.writeText(text);
this.message = this.$t('full_record.copied_link', { text: text});
} catch(err) {
this.message = this.$t('full_record.copied_link_failed', { text: text});
}
this.fadeOutMsg();
},
fadeOutMsg() {
setTimeout(() => this.message = '', 3000);
},
formatTimestamp(timestamp) {
return formatDistanceToNow(toDate(parseInt(timestamp)));
},
generateUrl(basePath, accessCode) {
return "https://" + basePath + "/services/api/single_use_link/" + accessCode;
}
}
}
</script>

<style scoped lang="scss">
.header-button-single-download {
text-align: right;
.single-download {
display: block;
a {
float: right;
max-width: 210px;
}
ul {
margin-top: 10px;
li {
.download-link-wrapper {
align-items: center;
display: inline-flex;
margin: 5px auto;
div {
background-color: white;
padding: 15px;
}
}
}
}
}
.single-use-msg-text {
display: none;
word-break: break-word;
padding: 5px;
}
.display-msg {
background: white;
border: 1px solid;
border-radius: 5px;
display: block;
height: auto;
padding: 5px;
position: fixed;
right: 10px;
text-align: center;
top: 10px;
width: auto;
z-index: 599;
}
}
@media (max-width: 768px) {
.header-button-single-download {
text-align: left;
.single-download {
display: block;
a {
float: none;
}
ul {
li {
margin-left: 0;
}
}
}
}
}
</style>
5 changes: 5 additions & 0 deletions static/js/vue-cdr-access/src/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ export default {
available_date: "Available after {available_date}",
collection_id: "Archival Collection ID",
contains: "Contains",
copied_link: "Download URL, {text}, copied to clipboard",
copied_link_failed: "Unable to copy download URL, {text}, to clipboard",
created_link: "Created link {link} expires in {expire_time}",
created_link_failed: "Unable to create single use link for {uuid}",
creator: "Creator",
date_added: "Date Added",
date_created: "Date Created",
detailed_metadata: "Detailed Metadata",
download: "Download",
download_file: "Download file",
download_single_use: "Generate Single-Use Link",
download_title: "Download {title}",
download_unavailable: "Download Unavailable",
edit: "Edit",
Expand Down
21 changes: 21 additions & 0 deletions static/js/vue-cdr-access/tests/unit/restrictedContent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {createTestingPinia} from '@pinia/testing';
import { useAccessStore } from '@/stores/access';
import restrictedContent from '@/components/full_record/restrictedContent.vue';
import displayWrapper from '@/components/displayWrapper.vue';
import singleUseLink from '@/components/full_record/singleUseLink.vue';
import {createI18n} from 'vue-i18n';
import translations from '@/translations';
import cloneDeep from 'lodash.clonedeep';
Expand Down Expand Up @@ -264,6 +265,26 @@ describe('restrictedContent.vue', () => {
expect(wrapper.find('.download').exists()).toBe(false);
});

it('displays a single use link button for files with the proper permissions', async () => {
const updated_data = cloneDeep(record);
updated_data.briefObject.permissions = ['viewAccessCopies', 'viewHidden', 'viewOriginal'];
await wrapper.setProps({
recordData: updated_data
});
expect(wrapper.findComponent(singleUseLink).exists()).toBe(true);
});

it('does not display a single use link button for files without the proper permissions', async () => {
const updated_data = cloneDeep(record);
updated_data.dataFileUrl = 'content/4db695c0-5fd5-4abf-9248-2e115d43f57d';
updated_data.resourceType = 'File';
updated_data.briefObject.permissions = ['viewAccessCopies'];
await wrapper.setProps({
recordData: updated_data
});
expect(wrapper.findComponent(singleUseLink).exists()).toBe(false);
});

it('does not show view options if content is public', async () => {
const updated_data = cloneDeep(record);
updated_data.briefObject.groupRoleMap = {
Expand Down
Loading

0 comments on commit 7561f6c

Please sign in to comment.