-
Notifications
You must be signed in to change notification settings - Fork 2
feat(admin): add admin settings for file sharing options #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace OCA\Zulip\Settings; | ||
|
|
||
| use OCA\Zulip\AppInfo\Application; | ||
| use OCP\AppFramework\Http\TemplateResponse; | ||
| use OCP\AppFramework\Services\IInitialState; | ||
| use OCP\IConfig; | ||
| use OCP\Settings\ISettings; | ||
|
|
||
| class Admin implements ISettings { | ||
|
|
||
| public function __construct( | ||
| private IConfig $config, | ||
| private IInitialState $initialStateService, | ||
| ) { | ||
| } | ||
|
|
||
| public function getForm(): TemplateResponse { | ||
| $adminConfig = [ | ||
| 'send_type_enabled_file' => $this->config->getAppValue(Application::APP_ID, 'send_type_enabled_file', '1') === '1', | ||
| 'send_type_enabled_public_link' => $this->config->getAppValue(Application::APP_ID, 'send_type_enabled_public_link', '1') === '1', | ||
| 'send_type_enabled_internal_link' => $this->config->getAppValue(Application::APP_ID, 'send_type_enabled_internal_link', '1') === '1', | ||
| 'send_type_default' => $this->config->getAppValue(Application::APP_ID, 'send_type_default', ''), | ||
| ]; | ||
| $this->initialStateService->provideInitialState('admin-config', $adminConfig); | ||
| return new TemplateResponse(Application::APP_ID, 'adminSettings'); | ||
| } | ||
|
|
||
| public function getSection(): string { | ||
| return 'connected-accounts'; | ||
| } | ||
|
|
||
| public function getPriority(): int { | ||
| return 10; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace OCA\Zulip\Settings; | ||
|
|
||
| use OCP\IL10N; | ||
| use OCP\IURLGenerator; | ||
| use OCP\Settings\IIconSection; | ||
|
|
||
| class AdminSection implements IIconSection { | ||
|
|
||
| public function __construct( | ||
| private IURLGenerator $urlGenerator, | ||
| private IL10N $l, | ||
| ) { | ||
| } | ||
|
|
||
| public function getID(): string { | ||
| return 'connected-accounts'; | ||
| } | ||
|
|
||
| public function getName(): string { | ||
| return $this->l->t('Connected accounts'); | ||
| } | ||
|
|
||
| public function getPriority(): int { | ||
| return 80; | ||
| } | ||
|
|
||
| public function getIcon(): string { | ||
| return $this->urlGenerator->imagePath('core', 'categories/integration.svg'); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { createApp } from 'vue' | ||
| import AdminSettings from './components/AdminSettings.vue' | ||
|
|
||
| const app = createApp(AdminSettings) | ||
| app.mixin({ methods: { t, n } }) | ||
| app.mount('#zulip_prefs') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| <template> | ||
| <div id="zulip_prefs" class="section"> | ||
| <h2> | ||
| <ZulipIcon class="icon" /> | ||
| {{ t('integration_zulip', 'Zulip integration') }} | ||
| </h2> | ||
| <div id="zulip-content"> | ||
| <h3>{{ t('integration_zulip', 'File sharing options') }}</h3> | ||
| <p class="settings-hint"> | ||
| {{ t('integration_zulip', 'Configure which sharing options are available to users when sending files to Zulip.') }} | ||
| </p> | ||
| <NcFormBox> | ||
| <NcFormBoxSwitch | ||
| v-model="state.send_type_enabled_file" | ||
| :disabled="isOnlyEnabled('file')" | ||
| @update:model-value="onCheckboxChanged($event, 'send_type_enabled_file')"> | ||
| {{ t('integration_zulip', 'Allow uploading files') }} | ||
| </NcFormBoxSwitch> | ||
| <NcFormBoxSwitch | ||
| v-model="state.send_type_enabled_public_link" | ||
| :disabled="isOnlyEnabled('public_link')" | ||
| @update:model-value="onCheckboxChanged($event, 'send_type_enabled_public_link')"> | ||
| {{ t('integration_zulip', 'Allow sending public links') }} | ||
| </NcFormBoxSwitch> | ||
| <NcFormBoxSwitch | ||
| v-model="state.send_type_enabled_internal_link" | ||
| :disabled="isOnlyEnabled('internal_link')" | ||
| @update:model-value="onCheckboxChanged($event, 'send_type_enabled_internal_link')"> | ||
| {{ t('integration_zulip', 'Allow sending internal links') }} | ||
| </NcFormBoxSwitch> | ||
| </NcFormBox> | ||
| <div v-if="enabledSendTypes.length > 1" class="default-type-section"> | ||
| <h3>{{ t('integration_zulip', 'Default sharing option') }}</h3> | ||
| <p class="settings-hint"> | ||
| {{ t('integration_zulip', 'Select which option is pre-selected when users open the sharing dialog.') }} | ||
|
Comment on lines
+32
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what do you think about having this section still visible when only one send option is available?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's pretty obvious, that's why it's hidden. But maybe a better UI design would be to have this part always visible and to disable unavailable choices? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah that could work too. |
||
| </p> | ||
| <div class="default-type-radios"> | ||
| <NcCheckboxRadioSwitch | ||
| v-model="defaultSendType" | ||
| value="first_available" | ||
| name="default_send_type_radio" | ||
| type="radio"> | ||
| {{ t('integration_zulip', 'First available option') }} | ||
| </NcCheckboxRadioSwitch> | ||
| <NcCheckboxRadioSwitch | ||
| v-if="state.send_type_enabled_file" | ||
| v-model="defaultSendType" | ||
| value="file" | ||
| name="default_send_type_radio" | ||
| type="radio"> | ||
| {{ t('integration_zulip', 'Upload files') }} | ||
| </NcCheckboxRadioSwitch> | ||
| <NcCheckboxRadioSwitch | ||
| v-if="state.send_type_enabled_public_link" | ||
| v-model="defaultSendType" | ||
| value="public_link" | ||
| name="default_send_type_radio" | ||
| type="radio"> | ||
| {{ t('integration_zulip', 'Public links') }} | ||
| </NcCheckboxRadioSwitch> | ||
| <NcCheckboxRadioSwitch | ||
| v-if="state.send_type_enabled_internal_link" | ||
| v-model="defaultSendType" | ||
| value="internal_link" | ||
| name="default_send_type_radio" | ||
| type="radio"> | ||
| {{ t('integration_zulip', 'Internal links') }} | ||
| </NcCheckboxRadioSwitch> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script> | ||
| import ZulipIcon from './icons/ZulipIcon.vue' | ||
|
|
||
| import NcFormBox from '@nextcloud/vue/components/NcFormBox' | ||
| import NcFormBoxSwitch from '@nextcloud/vue/components/NcFormBoxSwitch' | ||
| import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' | ||
|
|
||
| import axios from '@nextcloud/axios' | ||
| import { showSuccess, showError } from '@nextcloud/dialogs' | ||
| import { loadState } from '@nextcloud/initial-state' | ||
| import { generateUrl } from '@nextcloud/router' | ||
|
|
||
| export default { | ||
| name: 'AdminSettings', | ||
|
|
||
| components: { | ||
| ZulipIcon, | ||
| NcFormBox, | ||
| NcFormBoxSwitch, | ||
| NcCheckboxRadioSwitch, | ||
| }, | ||
|
|
||
| data() { | ||
| return { | ||
| state: loadState('integration_zulip', 'admin-config'), | ||
| } | ||
| }, | ||
|
|
||
| computed: { | ||
| enabledSendTypes() { | ||
| return [ | ||
| this.state.send_type_enabled_file && 'file', | ||
| this.state.send_type_enabled_public_link && 'public_link', | ||
| this.state.send_type_enabled_internal_link && 'internal_link', | ||
| ].filter(Boolean) | ||
| }, | ||
| defaultSendType: { | ||
| get() { | ||
| return this.state.send_type_default === '' ? 'first_available' : this.state.send_type_default | ||
| }, | ||
| set(value) { | ||
| this.onDefaultTypeChanged(value === 'first_available' ? '' : value) | ||
| }, | ||
| }, | ||
| }, | ||
|
|
||
| watch: { | ||
| enabledSendTypes(newTypes) { | ||
| if (this.state.send_type_default !== '' && !newTypes.includes(this.state.send_type_default)) { | ||
| this.onDefaultTypeChanged('') | ||
| } | ||
| }, | ||
| }, | ||
|
|
||
| methods: { | ||
| isOnlyEnabled(key) { | ||
| return this.enabledSendTypes.length === 1 && this.enabledSendTypes[0] === key | ||
| }, | ||
| onCheckboxChanged(newValue, key) { | ||
| this.saveAdminConfig({ [key]: newValue ? '1' : '0' }) | ||
| }, | ||
| onDefaultTypeChanged(value) { | ||
| this.state.send_type_default = value | ||
| this.saveAdminConfig({ send_type_default: value }) | ||
| }, | ||
| saveAdminConfig(values) { | ||
| const req = { values } | ||
| const url = generateUrl('/apps/integration_zulip/admin-config') | ||
| axios.put(url, req) | ||
| .then(() => { | ||
| showSuccess(t('integration_zulip', 'Zulip admin options saved')) | ||
| }) | ||
| .catch((error) => { | ||
| showError( | ||
| t('integration_zulip', 'Failed to save Zulip admin options') | ||
| + ': ' + (error.response?.request?.responseText ?? ''), | ||
| ) | ||
| console.error(error) | ||
| }) | ||
| }, | ||
| }, | ||
| } | ||
| </script> | ||
|
|
||
| <style scoped lang="scss"> | ||
| #zulip_prefs { | ||
| #zulip-content { | ||
| margin-left: 40px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 4px; | ||
| max-width: 800px; | ||
| } | ||
|
|
||
| h2 { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| justify-content: start; | ||
| } | ||
|
|
||
| h3 { | ||
| margin-top: 16px; | ||
| margin-bottom: 4px; | ||
| } | ||
|
|
||
| .settings-hint { | ||
| color: var(--color-text-maxcontrast); | ||
| margin-bottom: 8px; | ||
| } | ||
|
|
||
| .default-type-section { | ||
| margin-top: 16px; | ||
| } | ||
|
|
||
| .default-type-radios { | ||
| margin-left: 10px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 4px; | ||
| } | ||
| } | ||
| </style> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would read and inject these values in every page of nextcloud so is a bit wasteful
it would be better to add a
#[NoAdminRequired]path in ConfigController.php to read them from the filesplugin.js file