Skip to content

Commit 2660918

Browse files
authored
Merge pull request #6221 from LibreSign/backport/6220/stable32
[stable32] feat: signature flow toggle
2 parents 59d8db9 + b7124a5 commit 2660918

8 files changed

Lines changed: 120 additions & 39 deletions

File tree

lib/Controller/AdminController.php

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -898,34 +898,44 @@ public function footerTemplatePreviewPdf(string $template = '', int $width = 595
898898
/**
899899
* Set signature flow configuration
900900
*
901-
* @param string $mode Signature flow mode: 'parallel' or 'ordered_numeric'
901+
* @param bool $enabled Whether to force a signature flow for all documents
902+
* @param string|null $mode Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)
902903
* @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{}>
903904
*
904905
* 200: Configuration saved successfully
905906
* 400: Invalid signature flow mode provided
906907
* 500: Internal server error
907908
*/
908909
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/signature-flow/config', requirements: ['apiVersion' => '(v1)'])]
909-
public function setSignatureFlowConfig(string $mode): DataResponse {
910+
public function setSignatureFlowConfig(bool $enabled, ?string $mode = null): DataResponse {
910911
try {
911-
$signatureFlow = \OCA\Libresign\Enum\SignatureFlow::from($mode);
912-
} catch (\ValueError) {
913-
return new DataResponse([
914-
'error' => $this->l10n->t('Invalid signature flow mode. Use "parallel" or "ordered_numeric".'),
915-
], Http::STATUS_BAD_REQUEST);
916-
}
917-
918-
try {
919-
if ($signatureFlow === \OCA\Libresign\Enum\SignatureFlow::PARALLEL) {
912+
if (!$enabled) {
920913
$this->appConfig->deleteKey(Application::APP_ID, 'signature_flow');
921-
} else {
922-
$this->appConfig->setValueString(
923-
Application::APP_ID,
924-
'signature_flow',
925-
$signatureFlow->value
926-
);
914+
return new DataResponse([
915+
'message' => $this->l10n->t('Settings saved'),
916+
]);
917+
}
918+
919+
if ($mode === null) {
920+
return new DataResponse([
921+
'error' => $this->l10n->t('Mode is required when signature flow is enabled.'),
922+
], Http::STATUS_BAD_REQUEST);
923+
}
924+
925+
try {
926+
$signatureFlow = \OCA\Libresign\Enum\SignatureFlow::from($mode);
927+
} catch (\ValueError) {
928+
return new DataResponse([
929+
'error' => $this->l10n->t('Invalid signature flow mode. Use "parallel" or "ordered_numeric".'),
930+
], Http::STATUS_BAD_REQUEST);
927931
}
928932

933+
$this->appConfig->setValueString(
934+
Application::APP_ID,
935+
'signature_flow',
936+
$signatureFlow->value
937+
);
938+
929939
return new DataResponse([
930940
'message' => $this->l10n->t('Settings saved'),
931941
]);

lib/Settings/Admin.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
namespace OCA\Libresign\Settings;
1010

1111
use OCA\Libresign\AppInfo\Application;
12-
use OCA\Libresign\Enum\SignatureFlow;
1312
use OCA\Libresign\Exception\LibresignException;
1413
use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory;
1514
use OCA\Libresign\Service\CertificatePolicyService;
@@ -79,7 +78,7 @@ public function getForm(): TemplateResponse {
7978
$this->initialState->provideInitialState('tsa_username', $this->appConfig->getValueString(Application::APP_ID, 'tsa_username', ''));
8079
$this->initialState->provideInitialState('tsa_password', $this->appConfig->getValueString(Application::APP_ID, 'tsa_password', self::PASSWORD_PLACEHOLDER));
8180
$this->initialState->provideInitialState('docmdp_config', $this->docMdpConfigService->getConfig());
82-
$this->initialState->provideInitialState('signature_flow', $this->appConfig->getValueString(Application::APP_ID, 'signature_flow', SignatureFlow::PARALLEL->value));
81+
$this->initialState->provideInitialState('signature_flow', $this->appConfig->getValueString(Application::APP_ID, 'signature_flow', ''));
8382
return new TemplateResponse(Application::APP_ID, 'admin_settings');
8483
}
8584

openapi-administration.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2987,12 +2987,17 @@
29872987
"schema": {
29882988
"type": "object",
29892989
"required": [
2990-
"mode"
2990+
"enabled"
29912991
],
29922992
"properties": {
2993+
"enabled": {
2994+
"type": "boolean",
2995+
"description": "Whether to force a signature flow for all documents"
2996+
},
29932997
"mode": {
29942998
"type": "string",
2995-
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'"
2999+
"nullable": true,
3000+
"description": "Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)"
29963001
}
29973002
}
29983003
}

openapi-full.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11504,12 +11504,17 @@
1150411504
"schema": {
1150511505
"type": "object",
1150611506
"required": [
11507-
"mode"
11507+
"enabled"
1150811508
],
1150911509
"properties": {
11510+
"enabled": {
11511+
"type": "boolean",
11512+
"description": "Whether to force a signature flow for all documents"
11513+
},
1151011514
"mode": {
1151111515
"type": "string",
11512-
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'"
11516+
"nullable": true,
11517+
"description": "Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true)"
1151311518
}
1151411519
}
1151511520
}

src/types/openapi/openapi-administration.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,8 +1635,10 @@ export interface operations {
16351635
requestBody: {
16361636
content: {
16371637
"application/json": {
1638-
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' */
1639-
mode: string;
1638+
/** @description Whether to force a signature flow for all documents */
1639+
enabled: boolean;
1640+
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true) */
1641+
mode?: string | null;
16401642
};
16411643
};
16421644
};

src/types/openapi/openapi-full.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6048,8 +6048,10 @@ export interface operations {
60486048
requestBody: {
60496049
content: {
60506050
"application/json": {
6051-
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' */
6052-
mode: string;
6051+
/** @description Whether to force a signature flow for all documents */
6052+
enabled: boolean;
6053+
/** @description Signature flow mode: 'parallel' or 'ordered_numeric' (only used when enabled is true) */
6054+
mode?: string | null;
60536055
};
60546056
};
60556057
};

src/views/Settings/SignatureFlow.vue

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,26 @@
77
<NcNoteCard v-if="errorMessage" type="error">
88
{{ errorMessage }}
99
</NcNoteCard>
10-
<div class="signature-flow-options">
10+
11+
<div class="signature-flow-toggle">
12+
<NcCheckboxRadioSwitch type="switch"
13+
:checked="enabled"
14+
:disabled="loading"
15+
@update:checked="onToggleChange">
16+
<span>{{ t('libresign', 'Set default signing order') }}</span>
17+
</NcCheckboxRadioSwitch>
18+
<span v-if="loading && !flowChanging" class="toggle-status">
19+
<NcLoadingIcon :size="20" />
20+
</span>
21+
<span v-else-if="saved && !flowChanging" class="toggle-status">
22+
<NcSavingIndicatorIcon :size="20" />
23+
</span>
24+
<span v-else-if="showErrorIcon && !flowChanging" class="toggle-status">
25+
<NcSavingIndicatorIcon :size="20" error />
26+
</span>
27+
</div>
28+
29+
<div v-if="enabled" class="signature-flow-options">
1130
<NcCheckboxRadioSwitch v-for="flow in availableFlows"
1231
:key="flow.value"
1332
type="radio"
@@ -24,9 +43,9 @@
2443
</p>
2544
</div>
2645
<div v-if="selectedFlow?.value === flow.value" class="signature-flow-option-status">
27-
<NcLoadingIcon v-if="loading" :size="20" />
28-
<NcSavingIndicatorIcon v-else-if="saved" :size="20" />
29-
<NcSavingIndicatorIcon v-else-if="showErrorIcon" :size="20" error />
46+
<NcLoadingIcon v-if="loading && flowChanging" :size="20" />
47+
<NcSavingIndicatorIcon v-else-if="saved && flowChanging" :size="20" />
48+
<NcSavingIndicatorIcon v-else-if="showErrorIcon && flowChanging" :size="20" error />
3049
</div>
3150
</div>
3251
</NcCheckboxRadioSwitch>
@@ -58,6 +77,7 @@ export default {
5877
data() {
5978
return {
6079
name: t('libresign', 'Signing order'),
80+
enabled: false,
6181
selectedFlow: null,
6282
availableFlows: [
6383
{
@@ -75,6 +95,7 @@ export default {
7595
errorMessage: '',
7696
saved: false,
7797
showErrorIcon: false,
98+
flowChanging: false,
7899
}
79100
},
80101
async mounted() {
@@ -83,25 +104,40 @@ export default {
83104
methods: {
84105
loadConfig() {
85106
try {
86-
const mode = loadState('libresign', 'signature_flow', 'parallel')
87-
88-
this.selectedFlow = this.availableFlows.find(
89-
flow => flow.value === mode
90-
)
107+
const mode = loadState('libresign', 'signature_flow', null)
91108
92-
if (!this.selectedFlow) {
109+
if (mode === null || mode === '') {
110+
this.enabled = false
93111
this.selectedFlow = this.availableFlows[0]
112+
} else {
113+
this.enabled = true
114+
this.selectedFlow = this.availableFlows.find(
115+
flow => flow.value === mode
116+
)
117+
118+
if (!this.selectedFlow) {
119+
this.selectedFlow = this.availableFlows[0]
120+
}
94121
}
95122
} catch (error) {
96123
console.error('Error loading signature flow configuration:', error)
97124
this.errorMessage = t('libresign', 'Could not load configuration.')
125+
this.enabled = false
98126
this.selectedFlow = this.availableFlows[0]
99127
}
100128
},
129+
onToggleChange(value) {
130+
this.enabled = value
131+
this.errorMessage = ''
132+
this.showErrorIcon = false
133+
this.flowChanging = false
134+
this.saveConfig()
135+
},
101136
onFlowChange(value) {
102137
this.selectedFlow = this.availableFlows.find(flow => flow.value === value)
103138
this.errorMessage = ''
104139
this.showErrorIcon = false
140+
this.flowChanging = true
105141
this.saveConfig()
106142
},
107143
async saveConfig() {
@@ -113,12 +149,14 @@ export default {
113149
try {
114150
const url = generateOcsUrl('apps/libresign/api/v1/admin/signature-flow/config')
115151
await axios.post(url, {
116-
mode: this.selectedFlow?.value ?? 'parallel',
152+
enabled: this.enabled,
153+
mode: this.enabled ? (this.selectedFlow?.value ?? 'parallel') : null,
117154
})
118155
119156
this.saved = true
120157
setTimeout(() => {
121158
this.saved = false
159+
this.flowChanging = false
122160
}, 3000)
123161
} catch (error) {
124162
console.error('Error saving signature flow configuration:', error)
@@ -134,8 +172,27 @@ export default {
134172
</script>
135173
136174
<style lang="scss" scoped>
175+
.signature-flow-toggle {
176+
margin-bottom: 1.5rem;
177+
display: flex;
178+
align-items: center;
179+
gap: 0.5rem;
180+
181+
:deep(.checkbox-radio-switch) {
182+
flex-shrink: 0;
183+
}
184+
185+
.toggle-status {
186+
display: flex;
187+
align-items: center;
188+
flex-shrink: 0;
189+
}
190+
}
191+
137192
.signature-flow-options {
138193
margin-top: 0.5rem;
194+
margin-left: 2rem;
195+
padding-top: 0.5rem;
139196
140197
.signature-flow-option {
141198
display: flex;

tests/integration/features/sign/sequential_signing.feature

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ Feature: sequential-signing
3636
Given user "signer1" exists
3737
And user "signer2" exists
3838
And sending "post" to ocs "/apps/libresign/api/v1/admin/signature-flow/config"
39-
| mode | ordered_numeric |
39+
| enabled | true |
40+
| mode | ordered_numeric |
4041
And the response should have a status code 200
4142
When sending "post" to ocs "/apps/libresign/api/v1/request-signature"
4243
| file | {"url":"<BASE_URL>/apps/libresign/develop/pdf"} |

0 commit comments

Comments
 (0)