Signed-off-by: Louis Chemineau <louis@chmn.me>pull/35160/head
parent
e82bfba114
commit
629de6c8c9
@ -0,0 +1,36 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2022 Louis Chmn <louis@chmn.me> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_Versions\Versions; |
||||
|
||||
/** |
||||
* @since 26.0.0 |
||||
*/ |
||||
interface INameableVersionBackend { |
||||
/** |
||||
* Set the label for a version. |
||||
* |
||||
* @since 26.0.0 |
||||
*/ |
||||
public function setVersionLabel(IVersion $version, string $label): void; |
||||
} |
@ -0,0 +1,302 @@ |
||||
<!-- |
||||
- @copyright 2022 Carl Schwan <carl@carlschwan.eu> |
||||
- @license AGPL-3.0-or-later |
||||
- |
||||
- This program is free software: you can redistribute it and/or modify |
||||
- it under the terms of the GNU Affero General Public License as |
||||
- published by the Free Software Foundation, either version 3 of the |
||||
- License, or (at your option) any later version. |
||||
- |
||||
- This program is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
- GNU Affero General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Affero General Public License |
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
<template> |
||||
<div> |
||||
<NcListItem class="version" |
||||
:title="versionLabel" |
||||
:href="downloadURL" |
||||
:force-display-actions="true"> |
||||
<template #icon> |
||||
<img lazy="true" |
||||
:src="previewURL" |
||||
alt="" |
||||
height="256" |
||||
width="256" |
||||
class="version__image"> |
||||
</template> |
||||
<template #subtitle> |
||||
<div class="version__info"> |
||||
<span v-tooltip="formattedDate">{{ version.mtime | humanDateFromNow }}</span> |
||||
<!-- Separate dot to improve alignement --> |
||||
<span class="version__info__size">•</span> |
||||
<span class="version__info__size">{{ version.size | humanReadableSize }}</span> |
||||
</div> |
||||
</template> |
||||
<template #actions> |
||||
<NcActionButton v-if="capabilities.files.version_labeling === true" |
||||
:close-after-click="true" |
||||
@click="openVersionLabelModal"> |
||||
<template #icon> |
||||
<Pencil :size="22" /> |
||||
</template> |
||||
{{ version.label === '' ? t('files_versions', 'Name this version') : t('files_versions', 'Edit version name') }} |
||||
</NcActionButton> |
||||
<NcActionButton v-if="!isCurrent" |
||||
:close-after-click="true" |
||||
@click="restoreVersion"> |
||||
<template #icon> |
||||
<BackupRestore :size="22" /> |
||||
</template> |
||||
{{ t('files_versions', 'Restore version') }} |
||||
</NcActionButton> |
||||
<NcActionLink :href="downloadURL" |
||||
:close-after-click="true" |
||||
:download="downloadURL"> |
||||
<template #icon> |
||||
<Download :size="22" /> |
||||
</template> |
||||
{{ t('files_versions', 'Download version') }} |
||||
</NcActionLink> |
||||
<NcActionButton v-if="!isCurrent" |
||||
:close-after-click="true" |
||||
@click="deleteVersion"> |
||||
<template #icon> |
||||
<Delete :size="22" /> |
||||
</template> |
||||
{{ t('files_versions', 'Delete version') }} |
||||
</NcActionButton> |
||||
</template> |
||||
</NcListItem> |
||||
<NcModal v-if="showVersionLabelForm" |
||||
:title="t('files_versions', 'Name this version')" |
||||
@close="showVersionLabelForm = false"> |
||||
<form class="version-label-modal" |
||||
@submit.prevent="setVersionLabel(formVersionLabelValue)"> |
||||
<label> |
||||
<div class="version-label-modal__title">{{ t('photos', 'Version name') }}</div> |
||||
<NcTextField ref="labelInput" |
||||
:value.sync="formVersionLabelValue" |
||||
:placeholder="t('photos', 'Version name')" |
||||
:label-outside="true" /> |
||||
</label> |
||||
|
||||
<div class="version-label-modal__info"> |
||||
{{ t('photos', 'Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.') }} |
||||
</div> |
||||
|
||||
<div class="version-label-modal__actions"> |
||||
<NcButton :disabled="formVersionLabelValue.trim().length === 0" @click="setVersionLabel('')"> |
||||
{{ t('files_versions', 'Remove version name') }} |
||||
</NcButton> |
||||
<NcButton type="primary" native-type="submit"> |
||||
<template #icon> |
||||
<Check /> |
||||
</template> |
||||
{{ t('files_versions', 'Save version name') }} |
||||
</NcButton> |
||||
</div> |
||||
</form> |
||||
</NcModal> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import BackupRestore from 'vue-material-design-icons/BackupRestore.vue' |
||||
import Download from 'vue-material-design-icons/Download.vue' |
||||
import Pencil from 'vue-material-design-icons/Pencil.vue' |
||||
import Check from 'vue-material-design-icons/Check.vue' |
||||
import Delete from 'vue-material-design-icons/Delete' |
||||
import { NcActionButton, NcActionLink, NcListItem, NcModal, NcButton, NcTextField, Tooltip } from '@nextcloud/vue' |
||||
import moment from '@nextcloud/moment' |
||||
import { translate } from '@nextcloud/l10n' |
||||
import { joinPaths } from '@nextcloud/paths' |
||||
import { generateUrl } from '@nextcloud/router' |
||||
import { loadState } from '@nextcloud/initial-state' |
||||
|
||||
export default { |
||||
name: 'Version', |
||||
components: { |
||||
NcActionLink, |
||||
NcActionButton, |
||||
NcListItem, |
||||
NcModal, |
||||
NcButton, |
||||
NcTextField, |
||||
BackupRestore, |
||||
Download, |
||||
Pencil, |
||||
Check, |
||||
Delete, |
||||
}, |
||||
directives: { |
||||
tooltip: Tooltip, |
||||
}, |
||||
filters: { |
||||
/** |
||||
* @param {number} bytes |
||||
* @return {string} |
||||
*/ |
||||
humanReadableSize(bytes) { |
||||
return OC.Util.humanFileSize(bytes) |
||||
}, |
||||
/** |
||||
* @param {number} timestamp |
||||
* @return {string} |
||||
*/ |
||||
humanDateFromNow(timestamp) { |
||||
return moment(timestamp).fromNow() |
||||
}, |
||||
}, |
||||
props: { |
||||
/** @type {Vue.PropOptions<import('../utils/versions.js').Version>} */ |
||||
version: { |
||||
type: Object, |
||||
required: true, |
||||
}, |
||||
fileInfo: { |
||||
type: Object, |
||||
required: true, |
||||
}, |
||||
isCurrent: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
isFirstVersion: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
showVersionLabelForm: false, |
||||
formVersionLabelValue: this.version.label, |
||||
capabilities: loadState('core', 'capabilities', { files: { version_labeling: false } }), |
||||
} |
||||
}, |
||||
computed: { |
||||
/** |
||||
* @return {string} |
||||
*/ |
||||
versionLabel() { |
||||
if (this.isCurrent) { |
||||
if (this.version.label === '') { |
||||
return translate('files_versions', 'Current version') |
||||
} else { |
||||
return `${this.version.label} (${translate('files_versions', 'Current version')})` |
||||
} |
||||
} |
||||
|
||||
if (this.isFirstVersion && this.version.label === '') { |
||||
return translate('files_versions', 'Initial version') |
||||
} |
||||
|
||||
return this.version.label |
||||
}, |
||||
|
||||
/** |
||||
* @return {string} |
||||
*/ |
||||
downloadURL() { |
||||
if (this.isCurrent) { |
||||
return joinPaths('/remote.php/webdav', this.fileInfo.path, this.fileInfo.name) |
||||
} else { |
||||
return this.version.url |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* @return {string} |
||||
*/ |
||||
previewURL() { |
||||
if (this.isCurrent) { |
||||
return generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0', { |
||||
fileId: this.fileInfo.id, |
||||
fileEtag: this.fileInfo.etag, |
||||
}) |
||||
} else { |
||||
return this.version.preview |
||||
} |
||||
}, |
||||
}, |
||||
methods: { |
||||
openVersionLabelModal() { |
||||
this.showVersionLabelForm = true |
||||
this.$nextTick(() => { |
||||
this.$refs.labelInput.$el.getElementsByTagName('input')[0].focus() |
||||
}) |
||||
}, |
||||
|
||||
restoreVersion() { |
||||
this.$emit('restore', this.version) |
||||
}, |
||||
|
||||
setVersionLabel(label) { |
||||
this.formVersionLabelValue = label |
||||
this.showVersionLabelForm = false |
||||
this.$emit('label-update', this.version, label) |
||||
}, |
||||
|
||||
deleteVersion() { |
||||
this.$emit('delete', this.version) |
||||
}, |
||||
|
||||
formattedDate() { |
||||
return moment(this.version.mtime) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.version { |
||||
display: flex; |
||||
flex-direction: row; |
||||
|
||||
&__info { |
||||
display: flex; |
||||
flex-direction: row; |
||||
align-items: center; |
||||
gap: 0.5rem; |
||||
|
||||
&__size { |
||||
color: var(--color-text-lighter); |
||||
} |
||||
} |
||||
|
||||
&__image { |
||||
width: 3rem; |
||||
height: 3rem; |
||||
border: 1px solid var(--color-border); |
||||
border-radius: var(--border-radius-large); |
||||
} |
||||
} |
||||
|
||||
.version-label-modal { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
flex-direction: column; |
||||
height: 250px; |
||||
padding: 16px; |
||||
|
||||
&__title { |
||||
margin-bottom: 12px; |
||||
font-weight: 600; |
||||
} |
||||
|
||||
&__info { |
||||
margin-top: 12px; |
||||
color: var(--color-text-maxcontrast); |
||||
} |
||||
|
||||
&__actions { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
margin-top: 64px; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue