Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions lib/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -898,34 +898,44 @@ public function footerTemplatePreviewPdf(string $template = '', int $width = 595
/**
* Set signature flow configuration
*
* @param string $mode Signature flow mode: 'parallel' or 'ordered_numeric'
* @param bool $enabled Whether to force a signature flow for all documents
* @param string|null $mode Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)
* @return DataResponse<Http::STATUS_OK, array{message: string}, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: string}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{error: string}, array{}>
*
* 200: Configuration saved successfully
* 400: Invalid signature flow mode provided
* 500: Internal server error
*/
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/signature-flow/config', requirements: ['apiVersion' => '(v1)'])]
public function setSignatureFlowConfig(string $mode): DataResponse {
public function setSignatureFlowConfig(bool $enabled, ?string $mode = null): DataResponse {
try {
$signatureFlow = \OCA\Libresign\Enum\SignatureFlow::from($mode);
} catch (\ValueError) {
return new DataResponse([
'error' => $this->l10n->t('Invalid signature flow mode. Use "parallel" or "ordered_numeric".'),
], Http::STATUS_BAD_REQUEST);
}

try {
if ($signatureFlow === \OCA\Libresign\Enum\SignatureFlow::PARALLEL) {
if (!$enabled) {
$this->appConfig->deleteKey(Application::APP_ID, 'signature_flow');
} else {
$this->appConfig->setValueString(
Application::APP_ID,
'signature_flow',
$signatureFlow->value
);
return new DataResponse([
'message' => $this->l10n->t('Settings saved'),
]);
}

if ($mode === null) {
return new DataResponse([
'error' => $this->l10n->t('Mode is required when signature flow is enabled.'),
], Http::STATUS_BAD_REQUEST);
}

try {
$signatureFlow = \OCA\Libresign\Enum\SignatureFlow::from($mode);
} catch (\ValueError) {
return new DataResponse([
'error' => $this->l10n->t('Invalid signature flow mode. Use "parallel" or "ordered_numeric".'),
], Http::STATUS_BAD_REQUEST);
}

$this->appConfig->setValueString(
Application::APP_ID,
'signature_flow',
$signatureFlow->value
);

return new DataResponse([
'message' => $this->l10n->t('Settings saved'),
]);
Expand Down
3 changes: 1 addition & 2 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
namespace OCA\Libresign\Settings;

use OCA\Libresign\AppInfo\Application;
use OCA\Libresign\Enum\SignatureFlow;
use OCA\Libresign\Exception\LibresignException;
use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory;
use OCA\Libresign\Service\CertificatePolicyService;
Expand Down Expand Up @@ -79,7 +78,7 @@ public function getForm(): TemplateResponse {
$this->initialState->provideInitialState('tsa_username', $this->appConfig->getValueString(Application::APP_ID, 'tsa_username', ''));
$this->initialState->provideInitialState('tsa_password', $this->appConfig->getValueString(Application::APP_ID, 'tsa_password', self::PASSWORD_PLACEHOLDER));
$this->initialState->provideInitialState('docmdp_config', $this->docMdpConfigService->getConfig());
$this->initialState->provideInitialState('signature_flow', $this->appConfig->getValueString(Application::APP_ID, 'signature_flow', SignatureFlow::PARALLEL->value));
$this->initialState->provideInitialState('signature_flow', $this->appConfig->getValueString(Application::APP_ID, 'signature_flow', ''));
return new TemplateResponse(Application::APP_ID, 'admin_settings');
}

Expand Down
9 changes: 7 additions & 2 deletions openapi-administration.json
Original file line number Diff line number Diff line change
Expand Up @@ -2987,12 +2987,17 @@
"schema": {
"type": "object",
"required": [
"mode"
"enabled"
],
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether to force a signature flow for all documents"
},
"mode": {
"type": "string",
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'"
"nullable": true,
"description": "Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)"
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -11504,12 +11504,17 @@
"schema": {
"type": "object",
"required": [
"mode"
"enabled"
],
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether to force a signature flow for all documents"
},
"mode": {
"type": "string",
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'"
"nullable": true,
"description": "Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)"
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/types/openapi/openapi-administration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1635,8 +1635,10 @@ export interface operations {
requestBody: {
content: {
"application/json": {
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' */
mode: string;
/** @description Whether to force a signature flow for all documents */
enabled: boolean;
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true) */
mode?: string | null;
};
};
};
Expand Down
6 changes: 4 additions & 2 deletions src/types/openapi/openapi-full.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6048,8 +6048,10 @@ export interface operations {
requestBody: {
content: {
"application/json": {
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' */
mode: string;
/** @description Whether to force a signature flow for all documents */
enabled: boolean;
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true) */
mode?: string | null;
};
};
};
Expand Down
79 changes: 68 additions & 11 deletions src/views/Settings/SignatureFlow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,26 @@
<NcNoteCard v-if="errorMessage" type="error">
{{ errorMessage }}
</NcNoteCard>
<div class="signature-flow-options">

<div class="signature-flow-toggle">
<NcCheckboxRadioSwitch type="switch"
:checked="enabled"
:disabled="loading"
@update:checked="onToggleChange">
<span>{{ t('libresign', 'Set default signing order') }}</span>
</NcCheckboxRadioSwitch>
<span v-if="loading && !flowChanging" class="toggle-status">
<NcLoadingIcon :size="20" />
</span>
<span v-else-if="saved && !flowChanging" class="toggle-status">
<NcSavingIndicatorIcon :size="20" />
</span>
<span v-else-if="showErrorIcon && !flowChanging" class="toggle-status">
<NcSavingIndicatorIcon :size="20" error />
</span>
</div>

<div v-if="enabled" class="signature-flow-options">
<NcCheckboxRadioSwitch v-for="flow in availableFlows"
:key="flow.value"
type="radio"
Expand All @@ -24,9 +43,9 @@
</p>
</div>
<div v-if="selectedFlow?.value === flow.value" class="signature-flow-option-status">
<NcLoadingIcon v-if="loading" :size="20" />
<NcSavingIndicatorIcon v-else-if="saved" :size="20" />
<NcSavingIndicatorIcon v-else-if="showErrorIcon" :size="20" error />
<NcLoadingIcon v-if="loading && flowChanging" :size="20" />
<NcSavingIndicatorIcon v-else-if="saved && flowChanging" :size="20" />
<NcSavingIndicatorIcon v-else-if="showErrorIcon && flowChanging" :size="20" error />
</div>
</div>
</NcCheckboxRadioSwitch>
Expand Down Expand Up @@ -58,6 +77,7 @@ export default {
data() {
return {
name: t('libresign', 'Signing order'),
enabled: false,
selectedFlow: null,
availableFlows: [
{
Expand All @@ -75,6 +95,7 @@ export default {
errorMessage: '',
saved: false,
showErrorIcon: false,
flowChanging: false,
}
},
async mounted() {
Expand All @@ -83,25 +104,40 @@ export default {
methods: {
loadConfig() {
try {
const mode = loadState('libresign', 'signature_flow', 'parallel')

this.selectedFlow = this.availableFlows.find(
flow => flow.value === mode
)
const mode = loadState('libresign', 'signature_flow', null)

if (!this.selectedFlow) {
if (mode === null || mode === '') {
this.enabled = false
this.selectedFlow = this.availableFlows[0]
} else {
this.enabled = true
this.selectedFlow = this.availableFlows.find(
flow => flow.value === mode
)

if (!this.selectedFlow) {
this.selectedFlow = this.availableFlows[0]
}
}
} catch (error) {
console.error('Error loading signature flow configuration:', error)
this.errorMessage = t('libresign', 'Could not load configuration.')
this.enabled = false
this.selectedFlow = this.availableFlows[0]
}
},
onToggleChange(value) {
this.enabled = value
this.errorMessage = ''
this.showErrorIcon = false
this.flowChanging = false
this.saveConfig()
},
onFlowChange(value) {
this.selectedFlow = this.availableFlows.find(flow => flow.value === value)
this.errorMessage = ''
this.showErrorIcon = false
this.flowChanging = true
this.saveConfig()
},
async saveConfig() {
Expand All @@ -113,12 +149,14 @@ export default {
try {
const url = generateOcsUrl('apps/libresign/api/v1/admin/signature-flow/config')
await axios.post(url, {
mode: this.selectedFlow?.value ?? 'parallel',
enabled: this.enabled,
mode: this.enabled ? (this.selectedFlow?.value ?? 'parallel') : null,
})

this.saved = true
setTimeout(() => {
this.saved = false
this.flowChanging = false
}, 3000)
} catch (error) {
console.error('Error saving signature flow configuration:', error)
Expand All @@ -134,8 +172,27 @@ export default {
</script>

<style lang="scss" scoped>
.signature-flow-toggle {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.5rem;

:deep(.checkbox-radio-switch) {
flex-shrink: 0;
}

.toggle-status {
display: flex;
align-items: center;
flex-shrink: 0;
}
}

.signature-flow-options {
margin-top: 0.5rem;
margin-left: 2rem;
padding-top: 0.5rem;

.signature-flow-option {
display: flex;
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/features/sign/sequential_signing.feature
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ Feature: sequential-signing
Given user "signer1" exists
And user "signer2" exists
And sending "post" to ocs "/apps/libresign/api/v1/admin/signature-flow/config"
| mode | ordered_numeric |
| enabled | true |
| mode | ordered_numeric |
And the response should have a status code 200
When sending "post" to ocs "/apps/libresign/api/v1/request-signature"
| file | {"url":"<BASE_URL>/apps/libresign/develop/pdf"} |
Expand Down
Loading