Skip to content

Commit

Permalink
feat: Register new download limit entry
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Ng <chrng8@gmail.com>
  • Loading branch information
Pytal committed Mar 5, 2024
1 parent a64756a commit ffba227
Show file tree
Hide file tree
Showing 10 changed files with 20,807 additions and 12,999 deletions.
33,225 changes: 20,497 additions & 12,728 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@
},
"dependencies": {
"@nextcloud/axios": "^2.4.0",
"@nextcloud/dialogs": "^5.1.2",
"@nextcloud/initial-state": "^2.1.0",
"@nextcloud/l10n": "^2.2.0",
"@nextcloud/router": "^2.2.1",
"@nextcloud/vue": "^7.12.6",
"debounce": "^1.2.1",
"vue": "^2.7.16"
"@nextcloud/logger": "^2.7.0",
"@nextcloud/router": "^3.0.0",
"@nextcloud/sharing": "^0.1.0",
"@nextcloud/vue": "^8.7.1",
"vue": "^2.7.16",
"vue-frag": "^1.4.3"
},
"engines": {
"node": "^20.0.0",
Expand Down
67 changes: 67 additions & 0 deletions src/actions/DownloadLimitAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author Christopher Ng <chrng8@gmail.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @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/>.
*
*/

import { Type as ShareType } from '@nextcloud/sharing'

import DownloadLimitEntry from '../components/DownloadLimitEntry.vue'

interface ActionData {
share: any, // eslint-disable-line @typescript-eslint/no-explicit-any
fileInfo: any, // eslint-disable-line @typescript-eslint/no-explicit-any
[key: string]: unknown,
}

export class DownloadLimitAction {

get id() {
return 'files_downloadlimit'
}

get shareType() {
return [
ShareType.SHARE_TYPE_LINK,
ShareType.SHARE_TYPE_EMAIL,
]
}

data({ share, fileInfo }: ActionData) {
// Only works for files and existing shares
if (typeof share.token !== 'string' || fileInfo.type !== 'file') {
return {}
}

return {
is: DownloadLimitEntry,
share,
}
}

get advanced() {
return true
}

get handlers() {
return {}
}

}
186 changes: 186 additions & 0 deletions src/components/DownloadLimitEntry.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
<!--
- @copyright 2024 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- @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>
<Fragment>
<NcCheckboxRadioSwitch :checked.sync="limitEnabled"
:loading="loading"
:disabled="hasError">
{{ t('files_downloadlimit', 'Limit downloads') }}
</NcCheckboxRadioSwitch>
<template v-if="!loading && !hasError">
<NcNoteCard v-show="limitEnabled && showRemainingDownloadsNote"
class="action__count-note"
type="info">
{{ n('files_downloadlimit', '1 remaining download allowed', '{count} remaining downloads allowed', remainingCount, { count: remainingCount }) }}
</NcNoteCard>
<NcTextField v-show="limitEnabled"
:label="t('files_downloadlimit', 'Set download limit')"
type="number"
min="1"
:value.sync="limit"
:helper-text="helperText"
:error="Boolean(helperText)" />
<NcNoteCard v-show="limitEnabled && showResetNote"
class="action__reset-note"
type="warning">
{{ t('files_downloadlimit', 'Setting a new limit will reset the download count') }}
</NcNoteCard>
</template>
</Fragment>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { Fragment } from 'vue-frag'
import { showError } from '@nextcloud/dialogs'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import {
getDownloadLimit,
setDownloadLimit,
deleteDownloadLimit,
} from '../services/DownloadLimitService.ts'
import { logger } from '../logger.ts'
export default defineComponent({
name: 'DownloadLimitEntry',
components: {
Fragment,
NcCheckboxRadioSwitch,
NcNoteCard,
NcTextField,
},
props: {
share: {
type: Object,
required: true,
},
},
data() {
return {
limitEnabled: false,
initialLimit: null,
limit: '' as string | number, // input should be empty at first so initialize as empty string
count: null,
loading: false,
hasError: false,
}
},
computed: {
remainingCount() {
return this.initialLimit - this.count
},
helperText() {
if (this.limit > 0) {
return ''
}
return t('files_downloadlimit', 'The minimum limit is 1')
},
isNewShare() {
return this.share.id === null || this.share.id === undefined
},
showRemainingDownloadsNote() {
return typeof this.count === 'number'
},
showResetNote() {
return !this.isNewShare
&& Boolean(this.initialLimit)
&& typeof this.limit === 'number'
&& this.limit !== this.initialLimit
},
},
async created() {
logger.debug('Loading download limit', { share: this.share })
this.loading = true
try {
const { limit, count } = await getDownloadLimit(this.share.token)
if (typeof limit === 'number' && typeof count === 'number') {
this.limitEnabled = Boolean(limit)
this.initialLimit = limit
this.limit = limit
this.count = count
}
} catch (error) {
this.hasError = true
logger.error('Failed to load download limit', { error, share: this.share })
}
this.loading = false
},
watch: {
limit(limit) {
this.limit = Number(limit) // emitted <input> value is string so we parse it to number
},
},
methods: {
async onSave() {
const isValid = typeof this.limit === 'number' && this.limit > 0
if (!isValid) {
return
}
if (this.isNewShare || this.limit !== this.initialLimit) {
try {
await setDownloadLimit(this.share.token, this.limit)
} catch (error) {
showError(t('files_downloadlimit', 'Failed to set download limit'))
}
return
}
if (!this.limitEnabled && this.initialLimit) {
try {
await deleteDownloadLimit(this.share.token)
} catch (error) {
showError(t('files_downloadlimit', 'Failed to remove download limit'))
}
}
},
},
})
</script>

<style lang="scss" scoped>
.action {
&__count-note {
margin-top: 4px !important;
}
&__reset-note {
margin-bottom: 8px !important;
}
}
</style>
28 changes: 28 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @copyright 2024 Christopher Ng <chrng8@gmail.com>
*
* @author Christopher Ng <chrng8@gmail.com>
*
* @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/>.
*
*/

import { getLoggerBuilder } from '@nextcloud/logger'

export const logger = getLoggerBuilder()
.setApp('files_downloadlimit')
.detectUser()
.build()
16 changes: 6 additions & 10 deletions src/main.js → src/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author Christopher Ng <chrng8@gmail.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
* @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
Expand All @@ -20,14 +21,9 @@
*
*/

import LimitEnableAction from './models/LimitEnableAction'
import DownloadLimitAction from './models/DownloadLimitAction'
import Store from './models/Store'
import { DownloadLimitAction } from './actions/DownloadLimitAction.ts'

const store = new Store()

window.addEventListener('DOMContentLoaded', function() {
OCA.Sharing.ExternalShareActions.registerAction(new LimitEnableAction(store))
OCA.Sharing.ExternalShareActions.registerAction(new DownloadLimitAction(store))
console.debug('LimitEnableAction and DownloadLimitAction', appVersion, 'registered')
window.addEventListener('DOMContentLoaded', () => {
// @ts-expect-error OCA is not public
OCA.Sharing.ExternalShareActions.registerAction(new DownloadLimitAction())
})
Loading

0 comments on commit ffba227

Please sign in to comment.