Compare commits

...
46 changed files with 293 additions and 148 deletions
+50 -23
View File
@@ -5,52 +5,79 @@ on:
jobs: jobs:
Anti-slop: Anti-slop:
# Note: peakoss/anti-slop does not support the `issues` event yet (all of its # Note: peakoss/anti-slop does not support the `issues` event yet (all of its
# issue inputs are still commented out upstream), so the honeypot check that # issue inputs are still commented out upstream), so the checks that the PR Bot
# the PR Bot workflow gets from the action is implemented manually here. # workflow gets from the action are implemented manually here.
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write
steps: steps:
- name: Check for honeypot token - name: Check for slop signals
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with: with:
script: | script: |
const issue = context.payload.issue; const issue = context.payload.issue;
if (['OWNER', 'MEMBER', 'COLLABORATOR'].includes(issue.author_association)) { if (['OWNER', 'MEMBER', 'COLLABORATOR'].includes(issue.author_association)) {
core.info('Skipping check: user is a maintainer'); core.info('Skipping checks: user is a maintainer');
return; return;
} }
if (issue.user.type === 'Bot') { if (issue.user.type === 'Bot') {
core.info('Skipping check: user is a bot'); core.info('Skipping checks: user is a bot');
return; return;
} }
const haystack = `${issue.title}\n${issue.body ?? ''}`;
if (!haystack.toUpperCase().includes('ASLOP-PR-VERIFY')) {
core.info('Honeypot token not found');
return;
}
core.info('Honeypot token found, closing issue');
const common = { const common = {
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
issue_number: issue.number, issue_number: issue.number,
}; };
await github.rest.issues.createComment({ const contributing =
...common, 'https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md#use-of-ai-tools';
body: const codeOfConduct =
"This issue was automatically closed because it contains a marker that is only visible to " + 'https://github.com/paperless-ngx/paperless-ngx/blob/main/CODE_OF_CONDUCT.md';
"automated tools, which indicates it was generated by an AI agent without being disclosed as such.\n\n" + const newIssue = 'https://github.com/paperless-ngx/paperless-ngx/issues/new/choose';
"Please see our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md#use-of-ai-tools) " +
"and [Code of Conduct](https://github.com/paperless-ngx/paperless-ngx/blob/main/CODE_OF_CONDUCT.md). " +
"You are welcome to open a new issue that describes the problem you observed in your own words.",
});
// Honeypot: a token only an AI agent reading the raw issue template would include.
const haystack = `${issue.title}\n${issue.body ?? ''}`;
const honeypot = haystack.toUpperCase().includes('ASLOP-PR-VERIFY');
// Issues opened through the form always get the template's default labels. GitHub
// applies them a second or two *after* creation, so re-read them instead of trusting
// the webhook payload, and retry before concluding that there are none.
const templateLabels = ['bug', 'unconfirmed'];
let labels = [];
for (const delay of [0, 15000, 30000]) {
if (delay) await new Promise((resolve) => setTimeout(resolve, delay));
const { data } = await github.rest.issues.get({ ...common });
labels = data.labels.map((label) => (typeof label === 'string' ? label : label.name));
if (labels.some((label) => templateLabels.includes(label))) break;
}
const bypassedTemplate = !labels.some((label) => templateLabels.includes(label));
core.info(`Labels: [${labels.join(', ')}], honeypot: ${honeypot}, bypassed template: ${bypassedTemplate}`);
if (!honeypot && !bypassedTemplate) {
core.info('No slop signals found');
return;
}
// The honeypot is only ever tripped deliberately, so that message can name the cause.
// A missing template label only tells us the issue did not come from the form, which
// is reason enough to close it, but not proof of how it was written.
const body = honeypot
? 'This issue was automatically closed because it contains a marker that is only visible to ' +
'automated tools, which indicates it was generated by an AI agent without being disclosed as such.\n\n' +
`Please see our [contributing guidelines](${contributing}) and [Code of Conduct](${codeOfConduct}). ` +
'You are welcome to open a new issue that describes the problem you observed in your own words.'
: 'This issue was automatically closed because it was not opened using our bug report form. ' +
'Issues have to be created through the form so that the details we need to investigate are included.\n\n' +
`If the problem is still there, please [open a new issue](${newIssue}) using the form — that is all it takes ` +
'to get it looked at, and no other action is needed here.\n\n' +
'If any part of your report was written by an AI tool or agent, you must say so: undisclosed AI-generated ' +
`contributions are a violation of our [Code of Conduct](${codeOfConduct}), and such reports must describe the ` +
`behavior you observed only, without code analysis or suggested fixes. See our [contributing guidelines](${contributing}).`;
await github.rest.issues.createComment({ ...common, body });
await github.rest.issues.addLabels({ ...common, labels: ['ai'] }); await github.rest.issues.addLabels({ ...common, labels: ['ai'] });
await github.rest.issues.update({ ...common, state: 'closed', state_reason: 'not_planned' }); await github.rest.issues.update({ ...common, state: 'closed', state_reason: 'not_planned' });
+3 -1
View File
@@ -71,8 +71,10 @@
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"localize": true, "localize": true,
"assets": [ "assets": [
"src/favicon.ico",
"src/apple-touch-icon.png", "src/apple-touch-icon.png",
"src/icon-192.png",
"src/icon-512.png",
"src/icon-512-maskable.png",
"src/assets", "src/assets",
"src/manifest.webmanifest", "src/manifest.webmanifest",
{ {
+58 -47
View File
@@ -331,7 +331,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">86,87</context> <context context-type="linenumber">87,88</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
@@ -1880,7 +1880,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">162,163</context> <context context-type="linenumber">167,168</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
@@ -4104,7 +4104,7 @@
<source>Open date picker</source> <source>Open date picker</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">41</context> <context context-type="linenumber">42</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
@@ -4115,7 +4115,7 @@
<source>Today</source> <source>Today</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">46,47</context> <context context-type="linenumber">47,48</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
@@ -4146,7 +4146,7 @@
<source>Close</source> <source>Close</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">47,48</context> <context context-type="linenumber">48,49</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
@@ -4168,6 +4168,10 @@
<context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
<context context-type="linenumber">22,23</context> <context context-type="linenumber">22,23</context>
</context-group> </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
<context context-type="linenumber">155,156</context> <context context-type="linenumber">155,156</context>
@@ -4185,55 +4189,55 @@
<source>True</source> <source>True</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">54,55</context> <context context-type="linenumber">55,56</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">103,104</context> <context context-type="linenumber">107,108</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">109,110</context> <context context-type="linenumber">113,114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3800326155195149498" datatype="html"> <trans-unit id="3800326155195149498" datatype="html">
<source>False</source> <source>False</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">55,56</context> <context context-type="linenumber">56,57</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">104,105</context> <context context-type="linenumber">108,109</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">110,111</context> <context context-type="linenumber">114,115</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7551700625201096185" datatype="html"> <trans-unit id="7551700625201096185" datatype="html">
<source>Search docs...</source> <source>Search docs...</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">71</context> <context context-type="linenumber">73</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">126</context> <context context-type="linenumber">130</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2328549728463836983" datatype="html"> <trans-unit id="2328549728463836983" datatype="html">
<source>Remove query</source> <source>Remove query</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">149</context> <context context-type="linenumber">154</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3184700926171002527" datatype="html"> <trans-unit id="3184700926171002527" datatype="html">
<source>Any</source> <source>Any</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">160,161</context> <context context-type="linenumber">165,166</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
@@ -4244,28 +4248,28 @@
<source>Not</source> <source>Not</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">165,166</context> <context context-type="linenumber">170,171</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6548676277933116532" datatype="html"> <trans-unit id="6548676277933116532" datatype="html">
<source>Add query</source> <source>Add query</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">184</context> <context context-type="linenumber">189</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5599577087865387184" datatype="html"> <trans-unit id="5599577087865387184" datatype="html">
<source>Add expression</source> <source>Add expression</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">192</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7394978038852129121" datatype="html"> <trans-unit id="7394978038852129121" datatype="html">
<source>Remove expression</source> <source>Remove expression</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
<context context-type="linenumber">191</context> <context context-type="linenumber">196</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6630533861307510614" datatype="html"> <trans-unit id="6630533861307510614" datatype="html">
@@ -5973,46 +5977,53 @@
<context context-type="linenumber">468,469</context> <context context-type="linenumber">468,469</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7160869275743386191" datatype="html">
<source>This action runs in the background, so the suggestions may be applied after the other actions of this workflow have finished.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">469,470</context>
</context-group>
</trans-unit>
<trans-unit id="3473589590476379802" datatype="html"> <trans-unit id="3473589590476379802" datatype="html">
<source>Apply suggestions for</source> <source>Apply suggestions for</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">471,472</context> <context context-type="linenumber">472,473</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6859826074028847234" datatype="html"> <trans-unit id="6859826074028847234" datatype="html">
<source>Suggestions for fields that are not selected are discarded.</source> <source>Suggestions for fields that are not selected are discarded.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">476,477</context> <context context-type="linenumber">477,478</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1137167921211640884" datatype="html"> <trans-unit id="1137167921211640884" datatype="html">
<source>Create missing items</source> <source>Create missing items</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">486,487</context> <context context-type="linenumber">487,488</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="449779688394460071" datatype="html"> <trans-unit id="449779688394460071" datatype="html">
<source>Create suggested tags, correspondents and document types that do not exist yet.</source> <source>Create suggested tags, correspondents and document types that do not exist yet.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">488,489</context> <context context-type="linenumber">489,490</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5192325026233872238" datatype="html"> <trans-unit id="5192325026233872238" datatype="html">
<source>Overwrite existing values</source> <source>Overwrite existing values</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">496,497</context> <context context-type="linenumber">497,498</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9010697250406492150" datatype="html"> <trans-unit id="9010697250406492150" datatype="html">
<source>Apply suggestions even if the document already has a value. Tags are always added, never replaced.</source> <source>Apply suggestions even if the document already has a value. Tags are always added, never replaced.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">498,499</context> <context context-type="linenumber">499,500</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4626030417479279989" datatype="html"> <trans-unit id="4626030417479279989" datatype="html">
@@ -6692,6 +6703,10 @@
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
<context context-type="linenumber">162,163</context> <context context-type="linenumber">162,163</context>
</context-group> </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">85,86</context>
</context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-links-dialog/share-links-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-links-dialog/share-links-dialog.component.html</context>
<context context-type="linenumber">39,40</context> <context context-type="linenumber">39,40</context>
@@ -7240,7 +7255,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">88,89</context> <context context-type="linenumber">89,90</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
@@ -7335,7 +7350,7 @@
<source>Never</source> <source>Never</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">94,95</context> <context context-type="linenumber">95,96</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
@@ -7350,7 +7365,7 @@
<source>File version</source> <source>File version</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">97,98</context> <context context-type="linenumber">98,99</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
@@ -7361,7 +7376,7 @@
<source>Size</source> <source>Size</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">100,101</context> <context context-type="linenumber">101,102</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.html</context>
@@ -7372,14 +7387,14 @@
<source>A zip file containing the selected documents will be created for this share link bundle. This process happens in the background and may take some time, especially for large bundles.</source> <source>A zip file containing the selected documents will be created for this share link bundle. This process happens in the background and may take some time, especially for large bundles.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">110</context> <context context-type="linenumber">111</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7274497464693086242" datatype="html"> <trans-unit id="7274497464693086242" datatype="html">
<source>Manage share link bundles</source> <source>Manage share link bundles</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.html</context>
<context context-type="linenumber">114,115</context> <context context-type="linenumber">115,116</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
@@ -7390,25 +7405,14 @@
<source>Create share link bundle</source> <source>Create share link bundle</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context>
<context context-type="linenumber">61</context> <context context-type="linenumber">59</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2362798555008696742" datatype="html"> <trans-unit id="2362798555008696742" datatype="html">
<source>Create link</source> <source>Create link</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context>
<context context-type="linenumber">62</context> <context context-type="linenumber">60</context>
</context-group>
</trans-unit>
<trans-unit id="6826468215808575823" datatype="html">
<source>Share link copied to clipboard.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-dialog/share-link-bundle-dialog.component.ts</context>
<context context-type="linenumber">96</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.ts</context>
<context context-type="linenumber">111</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2044920992186463191" datatype="html"> <trans-unit id="2044920992186463191" datatype="html">
@@ -7492,6 +7496,13 @@
<context context-type="linenumber">67</context> <context context-type="linenumber">67</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6826468215808575823" datatype="html">
<source>Share link copied to clipboard.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-link-bundle-manage-dialog/share-link-bundle-manage-dialog.component.ts</context>
<context context-type="linenumber">111</context>
</context-group>
</trans-unit>
<trans-unit id="7268517108785510779" datatype="html"> <trans-unit id="7268517108785510779" datatype="html">
<source>Share link bundle deleted.</source> <source>Share link bundle deleted.</source>
<context-group purpose="location"> <context-group purpose="location">
@@ -8317,7 +8328,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/main.ts</context> <context context-type="sourcefile">src/main.ts</context>
<context context-type="linenumber">466</context> <context context-type="linenumber">469</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5028777105388019087" datatype="html"> <trans-unit id="5028777105388019087" datatype="html">
@@ -12740,14 +12751,14 @@
<source>Prev</source> <source>Prev</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/main.ts</context> <context context-type="sourcefile">src/main.ts</context>
<context context-type="linenumber">465</context> <context context-type="linenumber">468</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1241348629231510663" datatype="html"> <trans-unit id="1241348629231510663" datatype="html">
<source>End</source> <source>End</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/main.ts</context> <context context-type="sourcefile">src/main.ts</context>
<context context-type="linenumber">467</context> <context context-type="linenumber">470</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
</body> </body>
@@ -6,7 +6,7 @@
<div class="list-group list-group-flush" (keydown)="listKeyDown($event)"> <div class="list-group list-group-flush" (keydown)="listKeyDown($event)">
<div class="list-group-item"> <div class="list-group-item">
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<input class="form-control" type="text" [(ngModel)]="filterText" placeholder="Search fields" i18n-placeholder (keyup.enter)="listFilterEnter()" #listFilterTextInput> <input class="form-control" type="text" [(ngModel)]="filterText" [ngModelOptions]="{standalone: true}" placeholder="Search fields" i18n-placeholder (keyup.enter)="listFilterEnter()" #listFilterTextInput>
</div> </div>
</div> </div>
@for (field of filteredFields; track field.id) { @for (field of filteredFields; track field.id) {
@@ -35,6 +35,7 @@
@if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Date) { @if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Date) {
<input class="form-control" placeholder="yyyy-mm-dd" <input class="form-control" placeholder="yyyy-mm-dd"
[(ngModel)]="atom.value" [(ngModel)]="atom.value"
[ngModelOptions]="{standalone: true}"
ngbDatepicker ngbDatepicker
#d="ngbDatepicker" #d="ngbDatepicker"
[footerTemplate]="datePickerFooterTemplate" /> [footerTemplate]="datePickerFooterTemplate" />
@@ -48,9 +49,9 @@
</div> </div>
</ng-template> </ng-template>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Float || getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Integer) { } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Float || getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Integer) {
<input class="w-25 form-control rounded-end" type="number" [(ngModel)]="atom.value" [disabled]="disabled"> <input class="w-25 form-control rounded-end" type="number" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Boolean) { } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Boolean) {
<select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [disabled]="disabled"> <select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
<option value="true" i18n>True</option> <option value="true" i18n>True</option>
<option value="false" i18n>False</option> <option value="false" i18n>False</option>
</select> </select>
@@ -61,6 +62,7 @@
bindLabel="label" bindLabel="label"
bindValue="id" bindValue="id"
[(ngModel)]="atom.value" [(ngModel)]="atom.value"
[ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
[virtualScroll]="getSelectOptionsForField(atom.field)?.length > 100" [virtualScroll]="getSelectOptionsForField(atom.field)?.length > 100"
[searchFn]="selectOptionSearchFn" [searchFn]="selectOptionSearchFn"
@@ -68,14 +70,15 @@
(mousedown)="$event.stopImmediatePropagation()" (mousedown)="$event.stopImmediatePropagation()"
></ng-select> ></ng-select>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.DocumentLink) { } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.DocumentLink) {
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link> <pngx-input-document-link [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Monetary) { } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Monetary) {
<input class="w-25 form-control rounded-end" type="text" inputmode="decimal" <input class="w-25 form-control rounded-end" type="text" inputmode="decimal"
[ngModel]="atom.value" [ngModel]="atom.value"
[ngModelOptions]="{standalone: true}"
(ngModelChange)="setMonetaryValue(atom, $event)" (ngModelChange)="setMonetaryValue(atom, $event)"
[disabled]="disabled"> [disabled]="disabled">
} @else { } @else {
<input class="w-25 form-control rounded-end" type="text" [(ngModel)]="atom.value" [disabled]="disabled"> <input class="w-25 form-control rounded-end" type="text" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
} }
</ng-template> </ng-template>
@@ -85,6 +88,7 @@
class="paperless-input-select" class="paperless-input-select"
[items]="customFields()" [items]="customFields()"
[(ngModel)]="atom.field" [(ngModel)]="atom.field"
[ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
bindLabel="name" bindLabel="name"
bindValue="id" bindValue="id"
@@ -92,20 +96,20 @@
[appendTo]="selectAppendTo" [appendTo]="selectAppendTo"
(mousedown)="$event.stopImmediatePropagation()" (mousedown)="$event.stopImmediatePropagation()"
></ng-select> ></ng-select>
<select class="w-25 form-select" [(ngModel)]="atom.operator" [disabled]="disabled"> <select class="w-25 form-select" [(ngModel)]="atom.operator" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
@for (operator of getOperatorsForField(atom.field); track operator.label) { @for (operator of getOperatorsForField(atom.field); track operator.label) {
<option [ngValue]="operator.value">{{operator.label}}</option> <option [ngValue]="operator.value">{{operator.label}}</option>
} }
</select> </select>
@switch (atom.operator) { @switch (atom.operator) {
@case (CustomFieldQueryOperator.Exists) { @case (CustomFieldQueryOperator.Exists) {
<select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [disabled]="disabled"> <select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
<option value="true" i18n>True</option> <option value="true" i18n>True</option>
<option value="false" i18n>False</option> <option value="false" i18n>False</option>
</select> </select>
} }
@case (CustomFieldQueryOperator.IsNull) { @case (CustomFieldQueryOperator.IsNull) {
<select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [disabled]="disabled"> <select class="w-25 form-select rounded-end" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
<option value="true" i18n>True</option> <option value="true" i18n>True</option>
<option value="false" i18n>False</option> <option value="false" i18n>False</option>
</select> </select>
@@ -123,7 +127,7 @@
<ng-container *ngTemplateOutlet="comparisonValueTemplate; context: { atom: atom }"></ng-container> <ng-container *ngTemplateOutlet="comparisonValueTemplate; context: { atom: atom }"></ng-container>
} }
@case (CustomFieldQueryOperator.Contains) { @case (CustomFieldQueryOperator.Contains) {
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link> <pngx-input-document-link [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link>
} }
@case (CustomFieldQueryOperator.In) { @case (CustomFieldQueryOperator.In) {
<ng-select <ng-select
@@ -132,6 +136,7 @@
bindLabel="label" bindLabel="label"
bindValue="id" bindValue="id"
[(ngModel)]="atom.value" [(ngModel)]="atom.value"
[ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
[multiple]="true" [multiple]="true"
[searchFn]="selectOptionSearchFn" [searchFn]="selectOptionSearchFn"
@@ -143,7 +148,7 @@
<ng-container *ngTemplateOutlet="comparisonValueTemplate; context: { atom: atom }"></ng-container> <ng-container *ngTemplateOutlet="comparisonValueTemplate; context: { atom: atom }"></ng-container>
} }
@default { @default {
<input class="w-25 form-control rounded-end" type="text" [(ngModel)]="atom.value" [disabled]="disabled"> <input class="w-25 form-control rounded-end" type="text" [(ngModel)]="atom.value" [ngModelOptions]="{standalone: true}" [disabled]="disabled">
} }
} }
<button class="btn btn-link btn-sm text-danger pe-0" type="button" (click)="removeElement(atom)" [disabled]="disabled" aria-label="Remove query" i18n-aria-label> <button class="btn btn-link btn-sm text-danger pe-0" type="button" (click)="removeElement(atom)" [disabled]="disabled" aria-label="Remove query" i18n-aria-label>
@@ -156,12 +161,12 @@
<div class="d-flex w-100"> <div class="d-flex w-100">
<div class="d-flex flex-grow-1 flex-column"> <div class="d-flex flex-grow-1 flex-column">
<div class="btn-group btn-group-xs" role="group"> <div class="btn-group btn-group-xs" role="group">
<input [(ngModel)]="expression.operator" type="radio" class="btn-check" id="logicalOperatorOr_{{expression.id}}" name="logicalOperatorOr_{{expression.id}}" value="OR" [disabled]="expression.depth > 0 && expression.value.length < 2"> <input [(ngModel)]="expression.operator" [ngModelOptions]="{standalone: true}" type="radio" class="btn-check" id="logicalOperatorOr_{{expression.id}}" name="logicalOperatorOr_{{expression.id}}" value="OR" [disabled]="expression.depth > 0 && expression.value.length < 2">
<label class="btn btn-outline-primary" for="logicalOperatorOr_{{expression.id}}" i18n>Any</label> <label class="btn btn-outline-primary" for="logicalOperatorOr_{{expression.id}}" i18n>Any</label>
<input [(ngModel)]="expression.operator" type="radio" class="btn-check" id="logicalOperatorAnd_{{expression.id}}" name="logicalOperatorAnd_{{expression.id}}" value="AND" [disabled]="expression.depth > 0 && expression.value.length < 2"> <input [(ngModel)]="expression.operator" [ngModelOptions]="{standalone: true}" type="radio" class="btn-check" id="logicalOperatorAnd_{{expression.id}}" name="logicalOperatorAnd_{{expression.id}}" value="AND" [disabled]="expression.depth > 0 && expression.value.length < 2">
<label class="btn btn-outline-primary" for="logicalOperatorAnd_{{expression.id}}" i18n>All</label> <label class="btn btn-outline-primary" for="logicalOperatorAnd_{{expression.id}}" i18n>All</label>
@if (expression.negatable) { @if (expression.negatable) {
<input [(ngModel)]="expression.operator" type="radio" class="btn-check" id="logicalOperatorNot_{{expression.id}}" name="logicalOperatorNot_{{expression.id}}" value="NOT"> <input [(ngModel)]="expression.operator" [ngModelOptions]="{standalone: true}" type="radio" class="btn-check" id="logicalOperatorNot_{{expression.id}}" name="logicalOperatorNot_{{expression.id}}" value="NOT">
<label class="btn btn-outline-secondary" for="logicalOperatorNot_{{expression.id}}" i18n>Not</label> <label class="btn btn-outline-secondary" for="logicalOperatorNot_{{expression.id}}" i18n>Not</label>
} }
</div> </div>
@@ -466,6 +466,7 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<p class="text-muted small" i18n>The document will be sent to the configured AI service for suggestions. Consider costs and privacy.</p> <p class="text-muted small" i18n>The document will be sent to the configured AI service for suggestions. Consider costs and privacy.</p>
<p class="text-muted small" i18n>This action runs in the background, so the suggestions may be applied after the other actions of this workflow have finished.</p>
<pngx-input-select <pngx-input-select
i18n-title i18n-title
title="Apply suggestions for" title="Apply suggestions for"
@@ -12,7 +12,7 @@
} }
<div [ngClass]="{'col-md-9': horizontal, 'align-items-center': horizontal, 'd-flex': horizontal}"> <div [ngClass]="{'col-md-9': horizontal, 'align-items-center': horizontal, 'd-flex': horizontal}">
<div class="form-check"> <div class="form-check">
<input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled"> <input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
@if (!horizontal) { @if (!horizontal) {
<label class="form-check-label" [for]="inputId">{{title}}</label> <label class="form-check-label" [for]="inputId">{{title}}</label>
} }
@@ -12,7 +12,7 @@
</div> </div>
</ng-template> </ng-template>
<input #inputField class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" #colorPicker="ngbPopover" placement="bottom" popoverClass="shadow"> <input #inputField class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" #colorPicker="ngbPopover" placement="bottom" popoverClass="shadow">
<button class="btn btn-outline-secondary" type="button" (click)="randomize()" aria-label="Choose a random color" i18n-aria-label> <button class="btn btn-outline-secondary" type="button" (click)="randomize()" aria-label="Choose a random color" i18n-aria-label>
<i-bs name="dice5"></i-bs> <i-bs name="dice5"></i-bs>
@@ -6,26 +6,26 @@
align-items-center"> align-items-center">
@switch (getCustomField(fieldId)?.data_type) { @switch (getCustomField(fieldId)?.data_type) {
@case (CustomFieldDataType.String) { @case (CustomFieldDataType.String) {
<pngx-input-text [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-text [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true"></pngx-input-text> [horizontal]="true"></pngx-input-text>
} }
@case (CustomFieldDataType.Date) { @case (CustomFieldDataType.Date) {
<pngx-input-date [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-date [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true"></pngx-input-date> [horizontal]="true"></pngx-input-date>
} }
@case (CustomFieldDataType.Integer) { @case (CustomFieldDataType.Integer) {
<pngx-input-number [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-number [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true" [horizontal]="true"
[showAdd]="false"></pngx-input-number> [showAdd]="false"></pngx-input-number>
} }
@case (CustomFieldDataType.Float) { @case (CustomFieldDataType.Float) {
<pngx-input-number [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-number [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true" [horizontal]="true"
@@ -33,7 +33,7 @@
[step]=".1"></pngx-input-number> [step]=".1"></pngx-input-number>
} }
@case (CustomFieldDataType.Monetary) { @case (CustomFieldDataType.Monetary) {
<pngx-input-monetary [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-monetary [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[defaultCurrency]="getCustomField(fieldId)?.extra_data?.default_currency" [defaultCurrency]="getCustomField(fieldId)?.extra_data?.default_currency"
@@ -41,25 +41,25 @@
[horizontal]="true"></pngx-input-monetary> [horizontal]="true"></pngx-input-monetary>
} }
@case (CustomFieldDataType.Boolean) { @case (CustomFieldDataType.Boolean) {
<pngx-input-check [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-check [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true"></pngx-input-check> [horizontal]="true"></pngx-input-check>
} }
@case (CustomFieldDataType.Url) { @case (CustomFieldDataType.Url) {
<pngx-input-url [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-url [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true"></pngx-input-url> [horizontal]="true"></pngx-input-url>
} }
@case (CustomFieldDataType.DocumentLink) { @case (CustomFieldDataType.DocumentLink) {
<pngx-input-document-link [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-document-link [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[horizontal]="true"></pngx-input-document-link> [horizontal]="true"></pngx-input-document-link>
} }
@case (CustomFieldDataType.Select) { @case (CustomFieldDataType.Select) {
<pngx-input-select [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-select [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1" class="flex-grow-1"
[items]="getCustomField(fieldId)?.extra_data.select_options" [items]="getCustomField(fieldId)?.extra_data.select_options"
@@ -69,7 +69,7 @@
[horizontal]="true"></pngx-input-select> [horizontal]="true"></pngx-input-select>
} }
@case (CustomFieldDataType.LongText) { @case (CustomFieldDataType.LongText) {
<pngx-input-textarea [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)" <pngx-input-textarea [(ngModel)]="value[fieldId]" [ngModelOptions]="{standalone: true}" (ngModelChange)="onChange(value)"
[title]="getCustomField(fieldId)?.name" [title]="getCustomField(fieldId)?.name"
class="flex-grow-1"></pngx-input-textarea> class="flex-grow-1"></pngx-input-textarea>
} }
@@ -12,7 +12,7 @@
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
<input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10" <input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
(dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)" (dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled" [footerTemplate]="datePickerFooterTemplate"> name="dp" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled" [footerTemplate]="datePickerFooterTemplate">
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled" aria-label="Open date picker" i18n-aria-label> <button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled" aria-label="Open date picker" i18n-aria-label>
<i-bs width="1.2em" height="1.2em" name="calendar"></i-bs> <i-bs width="1.2em" height="1.2em" name="calendar"></i-bs>
</button> </button>
@@ -24,7 +24,7 @@
} }
<ng-template #select> <ng-template #select>
<ng-select name="inputId" [(ngModel)]="selectedDocuments" <ng-select name="inputId" [(ngModel)]="selectedDocuments" [ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
[items]="foundDocuments$ | async" [items]="foundDocuments$ | async"
[placeholder]="placeholder" [placeholder]="placeholder"
@@ -11,8 +11,8 @@
<div class="position-relative"> <div class="position-relative">
@for (entry of entries; let i = $index; track entry[0]) { @for (entry of entries; let i = $index; track entry[0]) {
<div class="input-group mb-3"> <div class="input-group mb-3">
<input type="text" class="form-control" [(ngModel)]="entry[0]" (change)="inputChange()" [disabled]="disabled" autocomplete="off"> <input type="text" class="form-control" [(ngModel)]="entry[0]" [ngModelOptions]="{standalone: true}" (change)="inputChange()" [disabled]="disabled" autocomplete="off">
<input type="text" class="form-control" [(ngModel)]="entry[1]" (change)="inputChange()" [disabled]="disabled" autocomplete="off"> <input type="text" class="form-control" [(ngModel)]="entry[1]" [ngModelOptions]="{standalone: true}" (change)="inputChange()" [disabled]="disabled" autocomplete="off">
<button type="button" class="btn btn-outline-secondary" (click)="removeEntry(i)" aria-label="Remove entry" i18n-aria-label> <button type="button" class="btn btn-outline-secondary" (click)="removeEntry(i)" aria-label="Remove entry" i18n-aria-label>
<i-bs class="text-danger" name="trash"></i-bs> <i-bs class="text-danger" name="trash"></i-bs>
</button> </button>
@@ -22,7 +22,7 @@
</button> </button>
</div> </div>
} }
<input #inputField type="hidden" class="form-control small" [(ngModel)]="value" [disabled]="true"> <input #inputField type="hidden" class="form-control small" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" [disabled]="true">
@if (hint) { @if (hint) {
<small class="form-text text-muted" [innerHTML]="hint"></small> <small class="form-text text-muted" [innerHTML]="hint"></small>
} }
@@ -13,8 +13,8 @@
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
<span class="input-group-text fw-bold bg-light">{{ monetaryValue | currency: currency }}</span> <span class="input-group-text fw-bold bg-light">{{ monetaryValue | currency: currency }}</span>
<input #currencyField class="form-control text-muted mw-60" [(ngModel)]="currency" (input)="currencyChange()" maxlength="3" [class.is-invalid]="error" [disabled]="disabled"> <input #currencyField class="form-control text-muted mw-60" [(ngModel)]="currency" [ngModelOptions]="{standalone: true}" (input)="currencyChange()" maxlength="3" [class.is-invalid]="error" [disabled]="disabled">
<input #monetaryValueField type="number" class="form-control text-muted" step=".01" [(ngModel)]="monetaryValue" (input)="monetaryValueChange()" (change)="monetaryValueChange(true)" [class.is-invalid]="error" [disabled]="disabled"> <input #monetaryValueField type="number" class="form-control text-muted" step=".01" [(ngModel)]="monetaryValue" [ngModelOptions]="{standalone: true}" (input)="monetaryValueChange()" (change)="monetaryValueChange(true)" [class.is-invalid]="error" [disabled]="disabled">
</div> </div>
<div class="invalid-feedback position-absolute top-100"> <div class="invalid-feedback position-absolute top-100">
{{error}} {{error}}
@@ -12,7 +12,7 @@
</div> </div>
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
<input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled"> <input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled">
@if (showAdd) { @if (showAdd) {
<button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button> <button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button>
} }
@@ -7,7 +7,7 @@
</div> </div>
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
<input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (focus)="onFocus()" (focusout)="onFocusOut()" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete"> <input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (focus)="onFocus()" (focusout)="onFocusOut()" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
@if (showReveal) { @if (showReveal) {
<button type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle"> <button type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle">
<i-bs name="eye"></i-bs> <i-bs name="eye"></i-bs>
@@ -1,6 +1,6 @@
<div class="paperless-input-select" [class.disabled]="disabled"> <div class="paperless-input-select" [class.disabled]="disabled">
<div> <div>
<ng-select name="inputId" [(ngModel)]="value" <ng-select name="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
clearable="true" clearable="true"
[items]="groups()" [items]="groups()"
@@ -1,6 +1,6 @@
<div class="paperless-input-select" [class.disabled]="disabled"> <div class="paperless-input-select" [class.disabled]="disabled">
<div> <div>
<ng-select name="inputId" [(ngModel)]="value" <ng-select name="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
clearable="true" clearable="true"
[items]="users()" [items]="users()"
@@ -14,7 +14,7 @@
} }
<div [class.col-md-9]="horizontal"> <div [class.col-md-9]="horizontal">
<div [class.input-group]="allowCreateNew || showFilter" [class.is-invalid]="error"> <div [class.input-group]="allowCreateNew || showFilter" [class.is-invalid]="error">
<ng-select name="inputId" [(ngModel)]="value" <ng-select name="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
[style.color]="textColor" [style.color]="textColor"
[style.background]="backgroundColor" [style.background]="backgroundColor"
@@ -17,7 +17,7 @@
} }
<div [ngClass]="{'align-items-center': horizontal, 'd-flex': horizontal}"> <div [ngClass]="{'align-items-center': horizontal, 'd-flex': horizontal}">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled"> <input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
@if (horizontal) { @if (horizontal) {
<label class="form-check-label" [class.text-muted]="showUnsetNote && isUnset" [for]="inputId" [ngbTooltip]="showUnsetNote && isUnset ? tipContent: null" placement="end"> <label class="form-check-label" [class.text-muted]="showUnsetNote && isUnset" [for]="inputId" [ngbTooltip]="showUnsetNote && isUnset ? tipContent: null" placement="end">
{{title}} {{title}}
@@ -7,7 +7,7 @@
} }
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group flex-nowrap"> <div class="input-group flex-nowrap">
<ng-select #tagSelect name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value" <ng-select #tagSelect name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value" [ngModelOptions]="{standalone: true}"
[disabled]="disabled" [disabled]="disabled"
[multiple]="multiple" [multiple]="multiple"
[closeOnSelect]="false" [closeOnSelect]="false"
@@ -11,7 +11,7 @@
} }
</div> </div>
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete" [placeholder]="placeholder"> <input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete" [placeholder]="placeholder">
@if (hint) { @if (hint) {
<small class="form-text text-muted" [innerHTML]="hint"></small> <small class="form-text text-muted" [innerHTML]="hint"></small>
} }
@@ -17,6 +17,7 @@
[class.is-invalid]="error" [class.is-invalid]="error"
[class.font-monospace]="monospace" [class.font-monospace]="monospace"
[(ngModel)]="value" [(ngModel)]="value"
[ngModelOptions]="{standalone: true}"
(change)="onChange(value)" (change)="onChange(value)"
[disabled]="disabled" [disabled]="disabled"
[placeholder]="placeholder" [placeholder]="placeholder"
@@ -10,7 +10,7 @@
</div> </div>
<div [class.col-md-9]="horizontal"> <div [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
<input #inputField type="url" class="form-control" [class.is-invalid]="error" placeholder="https://" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled"> <input #inputField type="url" class="form-control" [class.is-invalid]="error" placeholder="https://" [id]="inputId" [(ngModel)]="value" [ngModelOptions]="{standalone: true}" (change)="onChange(value)" [disabled]="disabled">
<a class="btn btn-outline-secondary rounded-end" title="Open link" i18n-title [href]="value" target="_blank"> <a class="btn btn-outline-secondary rounded-end" title="Open link" i18n-title [href]="value" target="_blank">
<i-bs width="1.2em" height="1.2em" name="box-arrow-up-right"></i-bs> <i-bs width="1.2em" height="1.2em" name="box-arrow-up-right"></i-bs>
</a> </a>
@@ -64,7 +64,7 @@
<dt class="col-sm-4" i18n>Slug</dt> <dt class="col-sm-4" i18n>Slug</dt>
<dd class="col-sm-8"><code>{{ createdBundle.slug }}</code></dd> <dd class="col-sm-8"><code>{{ createdBundle.slug }}</code></dd>
<dt class="col-sm-4" i18n>Link</dt> <dt class="col-sm-4" i18n>Link</dt>
<dd class="col-sm-8"> <dd class="col-sm-8 position-relative">
<label class="visually-hidden" for="shareBundleLink" i18n>Share link</label> <label class="visually-hidden" for="shareBundleLink" i18n>Share link</label>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<input id="shareBundleLink" class="form-control" type="text" [value]="getShareUrl(createdBundle)" readonly> <input id="shareBundleLink" class="form-control" type="text" [value]="getShareUrl(createdBundle)" readonly>
@@ -82,6 +82,7 @@
<span class="visually-hidden" i18n>Copy link</span> <span class="visually-hidden" i18n>Copy link</span>
</button> </button>
</div> </div>
<span class="badge bg-primary fade position-absolute top-50 end-0 translate-middle-y me-5 pe-none z-3" [class.show]="copied()" i18n>Copied!</span>
</dd> </dd>
<dt class="col-sm-4" i18n>Documents</dt> <dt class="col-sm-4" i18n>Documents</dt>
<dd class="col-sm-8">{{ createdBundle.document_count }}</dd> <dd class="col-sm-8">{{ createdBundle.document_count }}</dd>
@@ -115,7 +115,7 @@ describe('ShareLinkBundleDialogComponent', () => {
expect(copySpy).toHaveBeenCalledWith(component.getShareUrl(bundle)) expect(copySpy).toHaveBeenCalledWith(component.getShareUrl(bundle))
expect(component.copied()).toBe(true) expect(component.copied()).toBe(true)
expect(toastService.showInfo).toHaveBeenCalled() expect(toastService.showInfo).not.toHaveBeenCalled()
jest.advanceTimersByTime(3000) jest.advanceTimersByTime(3000)
expect(component.copied()).toBe(false) expect(component.copied()).toBe(false)
@@ -17,7 +17,6 @@ import {
} from 'src/app/data/share-link-bundle' } from 'src/app/data/share-link-bundle'
import { DocumentTitlePipe } from 'src/app/pipes/document-title.pipe' import { DocumentTitlePipe } from 'src/app/pipes/document-title.pipe'
import { FileSizePipe } from 'src/app/pipes/file-size.pipe' import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
import { ToastService } from 'src/app/services/toast.service'
import { environment } from 'src/environments/environment' import { environment } from 'src/environments/environment'
import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'
@@ -36,7 +35,6 @@ import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.compone
export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent { export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
private readonly formBuilder = inject(FormBuilder) private readonly formBuilder = inject(FormBuilder)
private readonly clipboard = inject(Clipboard) private readonly clipboard = inject(Clipboard)
private readonly toastService = inject(ToastService)
readonly documents = signal<Document[]>([]) readonly documents = signal<Document[]>([])
readonly selectionCount = signal(0) readonly selectionCount = signal(0)
@@ -80,6 +78,7 @@ export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
} }
this.buttonsEnabled.set(false) this.buttonsEnabled.set(false)
super.confirm() super.confirm()
this.cancelBtnCaption = $localize`Close`
} }
getShareUrl(bundle: ShareLinkBundleSummary): string { getShareUrl(bundle: ShareLinkBundleSummary): string {
@@ -93,7 +92,6 @@ export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
const success = this.clipboard.copy(this.getShareUrl(bundle)) const success = this.clipboard.copy(this.getShareUrl(bundle))
if (success) { if (success) {
this.copied.set(true) this.copied.set(true)
this.toastService.showInfo($localize`Share link copied to clipboard.`)
setTimeout(() => { setTimeout(() => {
this.copied.set(false) this.copied.set(false)
}, 3000) }, 3000)
@@ -0,0 +1,84 @@
import { LOCALE_ID } from '@angular/core'
import { TestBed } from '@angular/core/testing'
import { NgbInputDatepickerConfig } from '@ng-bootstrap/ng-bootstrap'
import { PngxDatePickerConfig } from './ngb-input-date-picker-config'
describe('PngxDatePickerConfig', () => {
const configureLocale = (locale: string) => {
TestBed.configureTestingModule({
providers: [
{ provide: LOCALE_ID, useValue: locale },
{
provide: NgbInputDatepickerConfig,
useClass: PngxDatePickerConfig,
},
],
})
}
it('uses Sunday as the first day of the week for en-US', () => {
configureLocale('en-US')
const config = TestBed.inject(NgbInputDatepickerConfig)
expect(config).toBeInstanceOf(PngxDatePickerConfig)
expect(config.firstDayOfWeek).toEqual(7)
})
it('uses Monday as the first day of the week for de-DE', () => {
configureLocale('de-DE')
const config = TestBed.inject(NgbInputDatepickerConfig)
expect(config.firstDayOfWeek).toEqual(1)
})
it('supports browsers that provide getWeekInfo() and weekInfo', () => {
const getWeekInfo = jest.fn().mockReturnValue({ firstDay: 6 })
const originalDescriptor = Object.getOwnPropertyDescriptor(
Intl.Locale.prototype,
'getWeekInfo'
)
Object.defineProperty(Intl.Locale.prototype, 'getWeekInfo', {
configurable: true,
value: getWeekInfo,
})
let config: NgbInputDatepickerConfig
try {
configureLocale('ar-EG')
config = TestBed.inject(NgbInputDatepickerConfig)
} finally {
if (originalDescriptor) {
Object.defineProperty(
Intl.Locale.prototype,
'getWeekInfo',
originalDescriptor
)
} else {
delete Intl.Locale.prototype['getWeekInfo']
}
}
expect(getWeekInfo).toHaveBeenCalledTimes(1)
expect(config.firstDayOfWeek).toEqual(6)
Object.defineProperty(Intl.Locale.prototype, 'weekInfo', {
configurable: true,
value: { firstDay: 5 },
})
Object.defineProperty(Intl.Locale.prototype, 'getWeekInfo', {
configurable: true,
value: undefined,
})
try {
TestBed.resetTestingModule()
configureLocale('ar-EG')
config = TestBed.inject(NgbInputDatepickerConfig)
} finally {
delete Intl.Locale.prototype['weekInfo']
delete Intl.Locale.prototype['getWeekInfo']
}
expect(config.firstDayOfWeek).toEqual(5)
})
})
@@ -0,0 +1,20 @@
import { inject, Injectable, LOCALE_ID } from '@angular/core'
import { NgbInputDatepickerConfig } from '@ng-bootstrap/ng-bootstrap'
@Injectable()
export class PngxDatePickerConfig extends NgbInputDatepickerConfig {
currentLocale = inject(LOCALE_ID)
constructor() {
super()
const localeInfo = new Intl.Locale(this.currentLocale) as any
let firstDay
if (localeInfo?.getWeekInfo) firstDay = localeInfo.getWeekInfo?.().firstDay
else if (localeInfo?.weekInfo?.firstDay)
firstDay = localeInfo.weekInfo.firstDay
if (firstDay !== undefined) {
this.firstDayOfWeek = firstDay
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.4 238.9" style="enable-background:new 0 0 198.4 238.9" xml:space="preserve">
<path d="M194.7 0C164.211 70.943 17.64 79.733 64.55 194.06c.59 1.468-10.848 17-18.47 29.897-1.758-6.453-3.816-13.486-3.516-14.075 38.109-45.141-27.26-70.643-30.776-107.583-16.423 29.318-22.286 80.623 27.25 110.23.29 0 2.637 11.138 3.816 16.712-1.169 2.348-2.348 4.695-2.927 6.454-1.168 2.926 7.622 2.637 7.622 3.226.879-.29 21.697-36.94 22.276-37.23C187.667 174.711 208.485 68.596 194.699 0zm-60.096 74.749c-55.11 49.246-64.49 85.897-62.732 103.777-18.47-43.682 35.772-91.76 62.732-103.777zM28.2 145.102c10.548 9.67 28.14 39.278 13.196 56.58 3.506-7.912 4.684-25.793-13.196-56.58z"/>
</svg>

Before

Width:  |  Height:  |  Size: 727 B

-4
View File
@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2897.4 896.6" style="enable-background:new 0 0 2897.4 896.6" xml:space="preserve">
<path d="M1022.3 428.7c-17.8-19.9-42.7-29.8-74.7-29.8-22.3 0-42.4 5.7-60.5 17.3-18.1 11.6-32.3 27.5-42.5 47.8s-15.3 42.9-15.3 67.8 5.1 47.5 15.3 67.8c10.3 20.3 24.4 36.2 42.5 47.8 18.1 11.5 38.3 17.3 60.5 17.3 32 0 56.9-9.9 74.7-29.8V655.5h84.5V408.3h-84.5v20.4zM1010.5 575c-10.2 11.7-23.6 17.6-40.2 17.6s-29.9-5.9-40-17.6-15.1-26.1-15.1-43.3c0-17.1 5-31.6 15.1-43.3s23.4-17.6 40-17.6 30 5.9 40.2 17.6 15.3 26.1 15.3 43.3-5.1 31.6-15.3 43.3zM1381 416.1c-18.1-11.5-38.3-17.3-60.5-17.4-32 0-56.9 9.9-74.7 29.8v-20.4h-84.5v390.7h84.5v-164c17.8 19.9 42.7 29.8 74.7 29.8 22.3 0 42.4-5.7 60.5-17.3s32.3-27.5 42.5-47.8c10.2-20.3 15.3-42.9 15.3-67.8s-5.1-47.5-15.3-67.8c-10.3-20.3-24.4-36.2-42.5-47.8zM1337.9 575c-10.1 11.7-23.4 17.6-40 17.6s-29.9-5.9-40-17.6-15.1-26.1-15.1-43.3c0-17.1 5-31.6 15.1-43.3s23.4-17.6 40-17.6 29.9 5.9 40 17.6 15.1 26.1 15.1 43.3-5.1 31.6-15.1 43.3zM1672.2 416.8c-20.5-12-43-18-67.6-18-24.9 0-47.6 5.9-68 17.6-20.4 11.7-36.5 27.7-48.2 48s-17.6 42.7-17.6 67.3c.3 25.2 6.2 47.8 17.8 68 11.5 20.2 28 36 49.3 47.6 21.3 11.5 45.9 17.3 73.8 17.3 48.6 0 86.8-14.7 114.7-44l-52.5-48.9c-8.6 8.3-17.6 14.6-26.7 19-9.3 4.3-21.1 6.4-35.3 6.4-11.6 0-22.5-3.6-32.7-10.9-10.3-7.3-17.1-16.5-20.7-27.8h180l.4-11.6c0-29.6-6-55.7-18-78.2s-28.3-39.8-48.7-51.8zm-113.9 86.4c2.1-12.1 7.5-21.8 16.2-29.1s18.7-10.9 30-10.9 21.2 3.6 29.8 10.9c8.6 7.2 13.9 16.9 16 29.1h-92zM1895.3 411.7c-11 5.6-20.3 13.7-28 24.4h-.1v-28h-84.5v247.3h84.5V536.3c0-22.6 4.7-38.1 14.2-46.5 9.5-8.5 22.7-12.7 39.6-12.7 6.2 0 13.5 1 21.8 3.1l10.7-72c-5.9-3.3-14.5-4.9-25.8-4.9-10.6 0-21.4 2.8-32.4 8.4zM1985 277.4h84.5v377.8H1985zM2313.2 416.8c-20.5-12-43-18-67.6-18-24.9 0-47.6 5.9-68 17.6s-36.5 27.7-48.2 48c-11.7 20.3-17.6 42.7-17.6 67.3.3 25.2 6.2 47.8 17.8 68 11.5 20.2 28 36 49.3 47.6 21.3 11.5 45.9 17.3 73.8 17.3 48.6 0 86.8-14.7 114.7-44l-52.5-48.9c-8.6 8.3-17.6 14.6-26.7 19-9.3 4.3-21.1 6.4-35.3 6.4-11.6 0-22.5-3.6-32.7-10.9-10.3-7.3-17.1-16.5-20.7-27.8h180l.4-11.6c0-29.6-6-55.7-18-78.2s-28.3-39.8-48.7-51.8zm-113.9 86.4c2.1-12.1 7.5-21.8 16.2-29.1s18.7-10.9 30-10.9 21.2 3.6 29.8 10.9c8.6 7.2 13.9 16.9 16 29.1h-92zM2583.6 507.7c-13.8-4.4-30.6-8.1-50.5-11.1-15.1-2.7-26.1-5.2-32.9-7.6-6.8-2.4-10.2-6.1-10.2-11.1s2.3-8.7 6.7-10.9c4.4-2.2 11.5-3.3 21.3-3.3 11.6 0 24.3 2.4 38.1 7.2 13.9 4.8 26.2 11 36.9 18.4l32.4-58.2c-11.3-7.4-26.2-14.7-44.9-21.8-18.7-7.1-39.6-10.7-62.7-10.7-33.7 0-60.2 7.6-79.3 22.7-19.1 15.1-28.7 36.1-28.7 63.1 0 19 4.8 33.9 14.4 44.7 9.6 10.8 21 18.5 34 22.9 13.1 4.5 28.9 8.3 47.6 11.6 14.6 2.7 25.1 5.3 31.6 7.8s9.8 6.5 9.8 11.8c0 10.4-9.7 15.6-29.3 15.6-13.7 0-28.5-2.3-44.7-6.9-16.1-4.6-29.2-11.3-39.3-20.2l-33.3 60c9.2 7.4 24.6 14.7 46.2 22 21.7 7.3 45.2 10.9 70.7 10.9 34.7 0 62.9-7.4 84.5-22.4 21.7-15 32.5-37.3 32.5-66.9 0-19.3-5-34.2-15.1-44.9s-22-18.3-35.8-22.7zM2883.4 575.3c0-19.3-5-34.2-15.1-44.9s-22-18.3-35.8-22.7c-13.8-4.4-30.6-8.1-50.5-11.1-15.1-2.7-26.1-5.2-32.9-7.6-6.8-2.4-10.2-6.1-10.2-11.1s2.3-8.7 6.7-10.9c4.4-2.2 11.5-3.3 21.3-3.3 11.6 0 24.3 2.4 38.1 7.2 13.9 4.8 26.2 11 36.9 18.4l32.4-58.2c-11.3-7.4-26.2-14.7-44.9-21.8-18.7-7.1-39.6-10.7-62.7-10.7-33.7 0-60.2 7.6-79.3 22.7-19.1 15.1-28.7 36.1-28.7 63.1 0 19 4.8 33.9 14.4 44.7 9.6 10.8 21 18.5 34 22.9 13.1 4.5 28.9 8.3 47.6 11.6 14.6 2.7 25.1 5.3 31.6 7.8s9.8 6.5 9.8 11.8c0 10.4-9.7 15.6-29.3 15.6-13.7 0-28.5-2.3-44.7-6.9-16.1-4.6-29.2-11.3-39.3-20.2l-33.3 60c9.2 7.4 24.6 14.7 46.2 22 21.7 7.3 45.2 10.9 70.7 10.9 34.7 0 62.9-7.4 84.5-22.4 21.7-15 32.5-37.3 32.5-66.9zM2460.7 738.7h59.6v17.2h-59.6zM2596.5 706.4c-5.7 0-11 1-15.8 3s-9 5-12.5 8.9v-9.4h-19.4v93.6h19.4v-52c0-8.6 2.1-15.3 6.3-20 4.2-4.7 9.5-7.1 15.9-7.1 7.8 0 13.4 2.3 16.8 6.7 3.4 4.5 5.1 11.3 5.1 20.5v52h19.4v-56.8c0-12.8-3.2-22.6-9.5-29.3-6.4-6.7-14.9-10.1-25.7-10.1zM2733.8 717.7c-3.6-3.4-7.9-6.1-13.1-8.2s-10.6-3.1-16.2-3.1c-8.7 0-16.5 2.1-23.5 6.3s-12.5 10-16.5 17.3c-4 7.3-6 15.4-6 24.4 0 8.9 2 17.1 6 24.3 4 7.3 9.5 13 16.5 17.2s14.9 6.3 23.5 6.3c5.6 0 11-1 16.2-3.1 5.1-2.1 9.5-4.8 13.1-8.2v24.4c0 8.5-2.5 14.8-7.6 18.7-5 3.9-11 5.9-18 5.9-6.7 0-12.4-1.6-17.3-4.7-4.8-3.1-7.6-7.7-8.3-13.8h-19.4c.6 7.7 2.9 14.2 7.1 19.5s9.6 9.3 16.2 12c6.6 2.7 13.8 4 21.7 4 12.8 0 23.5-3.4 32-10.1 8.6-6.7 12.8-17.1 12.8-31.1V708.9h-19.2v8.8zm-1.6 52.4c-2.5 4.7-6 8.3-10.4 11.2-4.4 2.7-9.4 4-14.9 4-5.7 0-10.8-1.4-15.2-4.3s-7.8-6.7-10.2-11.4c-2.3-4.8-3.5-9.8-3.5-15.2 0-5.5 1.1-10.6 3.5-15.3s5.8-8.5 10.2-11.3 9.5-4.2 15.2-4.2c5.5 0 10.5 1.4 14.9 4s7.9 6.3 10.4 11 3.8 10 3.8 15.8-1.3 11-3.8 15.7zM2867.9 708.9h-21.4l-25.6 33-25.4-33h-22.4l36 46.1-37.6 47.5h21.4l27.2-34.6 27.1 34.7h22.4l-37.6-48.2zM757.6 293.7c-20-10.8-42.6-16.2-67.8-16.2H600c-8.5 39.2-21.1 76.4-37.6 111.3-9.9 20.8-21.1 40.6-33.6 59.4v207.2h88.9V521.5h72c25.2 0 47.8-5.4 67.8-16.2s35.7-25.6 47.1-44.2c11.4-18.7 17.1-39.1 17.1-61.3.1-22.7-5.6-43.3-17-61.9-11.4-18.7-27.1-33.4-47.1-44.2zm-41 140.6c-9.3 8.9-21.6 13.3-36.7 13.3l-62.2.4v-92.5l62.2-.4c15.1 0 27.3 4.4 36.7 13.3 9.4 8.9 14 19.9 14 32.9 0 13.2-4.6 24.1-14 33z"/>
<path d="M140 713.7c-3.4-16.4-10.3-49.1-11.2-49.1C-16.9 577.5.4 426.6 48.6 340.4 59 449 251.2 524 139.1 656.8c-.9 1.7 5.2 22.4 10.3 41.4 22.4-37.9 56-83.6 54.3-87.9C65.9 273.9 496.9 248.1 586.6 39.4c40.5 201.8-20.7 513.9-367.2 593.2-1.7.9-62.9 108.6-65.5 109.5 0-1.7-25.9-.9-22.4-9.5 1.6-5.2 5.1-12 8.5-18.9zm-4.3-81.1c44-50.9-7.8-137.9-38.8-166.4 52.6 90.5 49.1 143.1 38.8 166.4z" style="fill:#17541f"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.4 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="264.567" height="318.552" viewBox="0 0 70 84.284">
<path style="fill:#17541f;stroke-width:1.10017" d="M752.438 82.365C638.02 348.605 87.938 381.61 263.964 810.674c2.2 5.5-40.706 63.81-69.31 112.217-6.602-24.204-14.304-50.607-13.204-52.807C324.473 700.658 79.136 604.944 65.934 466.322 4.324 576.34-17.678 768.868 168.25 879.984c1.1 0 9.902 41.808 14.303 62.711-4.4 8.802-8.802 17.602-11.002 24.203-4.4 11.002 28.603 9.902 28.603 12.102 3.3-1.1 81.413-138.62 83.614-139.72 442.267-101.216 520.377-499.476 468.67-756.915ZM526.904 362.906c-206.831 184.828-242.036 322.35-235.435 389.46-69.31-163.926 134.22-344.353 235.435-389.46ZM127.543 626.947c39.606 36.306 105.616 147.422 49.508 212.332 13.202-29.704 17.602-96.814-49.508-212.332z" transform="matrix(.094 0 0 .094 -2.042 -7.742)" fill="#17541F"/>
</svg>

Before

Width:  |  Height:  |  Size: 855 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="264.567" height="318.552" viewBox="0 0 70 84.284">
<path style="fill:#fff;stroke-width:1.10017" d="M752.438 82.365C638.02 348.605 87.938 381.61 263.964 810.674c2.2 5.5-40.706 63.81-69.31 112.217-6.602-24.204-14.304-50.607-13.204-52.807C324.473 700.658 79.136 604.944 65.934 466.322 4.324 576.34-17.678 768.868 168.25 879.984c1.1 0 9.902 41.808 14.303 62.711-4.4 8.802-8.802 17.602-11.002 24.203-4.4 11.002 28.603 9.902 28.603 12.102 3.3-1.1 81.413-138.62 83.614-139.72 442.267-101.216 520.377-499.476 468.67-756.915ZM526.904 362.906c-206.831 184.828-242.036 322.35-235.435 389.46-69.31-163.926 134.22-344.353 235.435-389.46ZM127.543 626.947c39.606 36.306 105.616 147.422 49.508 212.332 13.202-29.704 17.602-96.814-49.508-212.332z" transform="matrix(.094 0 0 .094 -2.042 -7.742)" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 849 B

-4
View File
@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2897.4 896.6" style="enable-background:new 0 0 2897.4 896.6" xml:space="preserve">
<path d="M1022.3 428.7c-17.8-19.9-42.7-29.8-74.7-29.8-22.3 0-42.4 5.7-60.5 17.3-18.1 11.6-32.3 27.5-42.5 47.8s-15.3 42.9-15.3 67.8 5.1 47.5 15.3 67.8c10.3 20.3 24.4 36.2 42.5 47.8 18.1 11.5 38.3 17.3 60.5 17.3 32 0 56.9-9.9 74.7-29.8V655.5h84.5V408.3h-84.5v20.4zM1010.5 575c-10.2 11.7-23.6 17.6-40.2 17.6s-29.9-5.9-40-17.6-15.1-26.1-15.1-43.3c0-17.1 5-31.6 15.1-43.3s23.4-17.6 40-17.6 30 5.9 40.2 17.6 15.3 26.1 15.3 43.3-5.1 31.6-15.3 43.3zM1381 416.1c-18.1-11.5-38.3-17.3-60.5-17.4-32 0-56.9 9.9-74.7 29.8v-20.4h-84.5v390.7h84.5v-164c17.8 19.9 42.7 29.8 74.7 29.8 22.3 0 42.4-5.7 60.5-17.3s32.3-27.5 42.5-47.8c10.2-20.3 15.3-42.9 15.3-67.8s-5.1-47.5-15.3-67.8c-10.3-20.3-24.4-36.2-42.5-47.8zM1337.9 575c-10.1 11.7-23.4 17.6-40 17.6s-29.9-5.9-40-17.6-15.1-26.1-15.1-43.3c0-17.1 5-31.6 15.1-43.3s23.4-17.6 40-17.6 29.9 5.9 40 17.6 15.1 26.1 15.1 43.3-5.1 31.6-15.1 43.3zM1672.2 416.8c-20.5-12-43-18-67.6-18-24.9 0-47.6 5.9-68 17.6-20.4 11.7-36.5 27.7-48.2 48s-17.6 42.7-17.6 67.3c.3 25.2 6.2 47.8 17.8 68 11.5 20.2 28 36 49.3 47.6 21.3 11.5 45.9 17.3 73.8 17.3 48.6 0 86.8-14.7 114.7-44l-52.5-48.9c-8.6 8.3-17.6 14.6-26.7 19-9.3 4.3-21.1 6.4-35.3 6.4-11.6 0-22.5-3.6-32.7-10.9-10.3-7.3-17.1-16.5-20.7-27.8h180l.4-11.6c0-29.6-6-55.7-18-78.2s-28.3-39.8-48.7-51.8zm-113.9 86.4c2.1-12.1 7.5-21.8 16.2-29.1s18.7-10.9 30-10.9 21.2 3.6 29.8 10.9c8.6 7.2 13.9 16.9 16 29.1h-92zM1895.3 411.7c-11 5.6-20.3 13.7-28 24.4h-.1v-28h-84.5v247.3h84.5V536.3c0-22.6 4.7-38.1 14.2-46.5 9.5-8.5 22.7-12.7 39.6-12.7 6.2 0 13.5 1 21.8 3.1l10.7-72c-5.9-3.3-14.5-4.9-25.8-4.9-10.6 0-21.4 2.8-32.4 8.4zM1985 277.4h84.5v377.8H1985zM2313.2 416.8c-20.5-12-43-18-67.6-18-24.9 0-47.6 5.9-68 17.6s-36.5 27.7-48.2 48c-11.7 20.3-17.6 42.7-17.6 67.3.3 25.2 6.2 47.8 17.8 68 11.5 20.2 28 36 49.3 47.6 21.3 11.5 45.9 17.3 73.8 17.3 48.6 0 86.8-14.7 114.7-44l-52.5-48.9c-8.6 8.3-17.6 14.6-26.7 19-9.3 4.3-21.1 6.4-35.3 6.4-11.6 0-22.5-3.6-32.7-10.9-10.3-7.3-17.1-16.5-20.7-27.8h180l.4-11.6c0-29.6-6-55.7-18-78.2s-28.3-39.8-48.7-51.8zm-113.9 86.4c2.1-12.1 7.5-21.8 16.2-29.1s18.7-10.9 30-10.9 21.2 3.6 29.8 10.9c8.6 7.2 13.9 16.9 16 29.1h-92zM2583.6 507.7c-13.8-4.4-30.6-8.1-50.5-11.1-15.1-2.7-26.1-5.2-32.9-7.6-6.8-2.4-10.2-6.1-10.2-11.1s2.3-8.7 6.7-10.9c4.4-2.2 11.5-3.3 21.3-3.3 11.6 0 24.3 2.4 38.1 7.2 13.9 4.8 26.2 11 36.9 18.4l32.4-58.2c-11.3-7.4-26.2-14.7-44.9-21.8-18.7-7.1-39.6-10.7-62.7-10.7-33.7 0-60.2 7.6-79.3 22.7-19.1 15.1-28.7 36.1-28.7 63.1 0 19 4.8 33.9 14.4 44.7 9.6 10.8 21 18.5 34 22.9 13.1 4.5 28.9 8.3 47.6 11.6 14.6 2.7 25.1 5.3 31.6 7.8s9.8 6.5 9.8 11.8c0 10.4-9.7 15.6-29.3 15.6-13.7 0-28.5-2.3-44.7-6.9-16.1-4.6-29.2-11.3-39.3-20.2l-33.3 60c9.2 7.4 24.6 14.7 46.2 22 21.7 7.3 45.2 10.9 70.7 10.9 34.7 0 62.9-7.4 84.5-22.4 21.7-15 32.5-37.3 32.5-66.9 0-19.3-5-34.2-15.1-44.9s-22-18.3-35.8-22.7zM2883.4 575.3c0-19.3-5-34.2-15.1-44.9s-22-18.3-35.8-22.7c-13.8-4.4-30.6-8.1-50.5-11.1-15.1-2.7-26.1-5.2-32.9-7.6-6.8-2.4-10.2-6.1-10.2-11.1s2.3-8.7 6.7-10.9c4.4-2.2 11.5-3.3 21.3-3.3 11.6 0 24.3 2.4 38.1 7.2 13.9 4.8 26.2 11 36.9 18.4l32.4-58.2c-11.3-7.4-26.2-14.7-44.9-21.8-18.7-7.1-39.6-10.7-62.7-10.7-33.7 0-60.2 7.6-79.3 22.7-19.1 15.1-28.7 36.1-28.7 63.1 0 19 4.8 33.9 14.4 44.7 9.6 10.8 21 18.5 34 22.9 13.1 4.5 28.9 8.3 47.6 11.6 14.6 2.7 25.1 5.3 31.6 7.8s9.8 6.5 9.8 11.8c0 10.4-9.7 15.6-29.3 15.6-13.7 0-28.5-2.3-44.7-6.9-16.1-4.6-29.2-11.3-39.3-20.2l-33.3 60c9.2 7.4 24.6 14.7 46.2 22 21.7 7.3 45.2 10.9 70.7 10.9 34.7 0 62.9-7.4 84.5-22.4 21.7-15 32.5-37.3 32.5-66.9zM2460.7 738.7h59.6v17.2h-59.6zM2596.5 706.4c-5.7 0-11 1-15.8 3s-9 5-12.5 8.9v-9.4h-19.4v93.6h19.4v-52c0-8.6 2.1-15.3 6.3-20 4.2-4.7 9.5-7.1 15.9-7.1 7.8 0 13.4 2.3 16.8 6.7 3.4 4.5 5.1 11.3 5.1 20.5v52h19.4v-56.8c0-12.8-3.2-22.6-9.5-29.3-6.4-6.7-14.9-10.1-25.7-10.1zM2733.8 717.7c-3.6-3.4-7.9-6.1-13.1-8.2s-10.6-3.1-16.2-3.1c-8.7 0-16.5 2.1-23.5 6.3s-12.5 10-16.5 17.3c-4 7.3-6 15.4-6 24.4 0 8.9 2 17.1 6 24.3 4 7.3 9.5 13 16.5 17.2s14.9 6.3 23.5 6.3c5.6 0 11-1 16.2-3.1 5.1-2.1 9.5-4.8 13.1-8.2v24.4c0 8.5-2.5 14.8-7.6 18.7-5 3.9-11 5.9-18 5.9-6.7 0-12.4-1.6-17.3-4.7-4.8-3.1-7.6-7.7-8.3-13.8h-19.4c.6 7.7 2.9 14.2 7.1 19.5s9.6 9.3 16.2 12c6.6 2.7 13.8 4 21.7 4 12.8 0 23.5-3.4 32-10.1 8.6-6.7 12.8-17.1 12.8-31.1V708.9h-19.2v8.8zm-1.6 52.4c-2.5 4.7-6 8.3-10.4 11.2-4.4 2.7-9.4 4-14.9 4-5.7 0-10.8-1.4-15.2-4.3s-7.8-6.7-10.2-11.4c-2.3-4.8-3.5-9.8-3.5-15.2 0-5.5 1.1-10.6 3.5-15.3s5.8-8.5 10.2-11.3 9.5-4.2 15.2-4.2c5.5 0 10.5 1.4 14.9 4s7.9 6.3 10.4 11 3.8 10 3.8 15.8-1.3 11-3.8 15.7zM2867.9 708.9h-21.4l-25.6 33-25.4-33h-22.4l36 46.1-37.6 47.5h21.4l27.2-34.6 27.1 34.7h22.4l-37.6-48.2zM757.6 293.7c-20-10.8-42.6-16.2-67.8-16.2H600c-8.5 39.2-21.1 76.4-37.6 111.3-9.9 20.8-21.1 40.6-33.6 59.4v207.2h88.9V521.5h72c25.2 0 47.8-5.4 67.8-16.2s35.7-25.6 47.1-44.2c11.4-18.7 17.1-39.1 17.1-61.3.1-22.7-5.6-43.3-17-61.9-11.4-18.7-27.1-33.4-47.1-44.2zm-41 140.6c-9.3 8.9-21.6 13.3-36.7 13.3l-62.2.4v-92.5l62.2-.4c15.1 0 27.3 4.4 36.7 13.3 9.4 8.9 14 19.9 14 32.9 0 13.2-4.6 24.1-14 33z"/>
<path d="M140 713.7c-3.4-16.4-10.3-49.1-11.2-49.1C-16.9 577.5.4 426.6 48.6 340.4 59 449 251.2 524 139.1 656.8c-.9 1.7 5.2 22.4 10.3 41.4 22.4-37.9 56-83.6 54.3-87.9C65.9 273.9 496.9 248.1 586.6 39.4c40.5 201.8-20.7 513.9-367.2 593.2-1.7.9-62.9 108.6-65.5 109.5 0-1.7-25.9-.9-22.4-9.5 1.6-5.2 5.1-12 8.5-18.9zm-4.3-81.1c44-50.9-7.8-137.9-38.8-166.4 52.6 90.5 49.1 143.1 38.8 166.4z" style="fill:#17541f"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

-1
View File
@@ -8,7 +8,6 @@
<meta name="color-scheme" content="dark light"> <meta name="color-scheme" content="dark light">
<meta name="theme-color" content="#17541f" /> <meta name="theme-color" content="#17541f" />
<link rel="manifest" href="manifest.webmanifest"> <link rel="manifest" href="manifest.webmanifest">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="apple-touch-icon" href="apple-touch-icon.png"> <link rel="apple-touch-icon" href="apple-touch-icon.png">
</head> </head>
<body> <body>
+3
View File
@@ -18,6 +18,7 @@ import { BrowserModule, bootstrapApplication } from '@angular/platform-browser'
import { import {
NgbDateAdapter, NgbDateAdapter,
NgbDateParserFormatter, NgbDateParserFormatter,
NgbInputDatepickerConfig,
NgbModule, NgbModule,
} from '@ng-bootstrap/ng-bootstrap' } from '@ng-bootstrap/ng-bootstrap'
import { NgSelectModule } from '@ng-select/ng-select' import { NgSelectModule } from '@ng-select/ng-select'
@@ -227,6 +228,7 @@ import { provideUiTour } from 'ngx-ui-tour-ng-bootstrap'
import { CorrespondentNamePipe } from './app/pipes/correspondent-name.pipe' import { CorrespondentNamePipe } from './app/pipes/correspondent-name.pipe'
import { DocumentTypeNamePipe } from './app/pipes/document-type-name.pipe' import { DocumentTypeNamePipe } from './app/pipes/document-type-name.pipe'
import { StoragePathNamePipe } from './app/pipes/storage-path-name.pipe' import { StoragePathNamePipe } from './app/pipes/storage-path-name.pipe'
import { PngxDatePickerConfig } from './app/utils/ngb-input-date-picker-config'
registerLocaleData(localeAf) registerLocaleData(localeAf)
registerLocaleData(localeAr) registerLocaleData(localeAr)
@@ -439,6 +441,7 @@ bootstrapApplication(AppComponent, {
CookieService, CookieService,
FilterPipe, FilterPipe,
DocumentTitlePipe, DocumentTitlePipe,
{ provide: NgbInputDatepickerConfig, useClass: PngxDatePickerConfig },
{ provide: NgbDateAdapter, useClass: ISODateAdapter }, { provide: NgbDateAdapter, useClass: ISODateAdapter },
{ provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter }, { provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter },
PermissionsGuard, PermissionsGuard,
+12 -4
View File
@@ -4,12 +4,20 @@
"display": "standalone", "display": "standalone",
"icons": [ "icons": [
{ {
"src": "favicon.ico", "src": "icon-192.png",
"sizes": "256x256" "sizes": "192x192",
"type": "image/png"
}, },
{ {
"src": "assets/logo-notext.svg", "src": "icon-512.png",
"sizes": "any" "sizes": "512x512",
"type": "image/png"
},
{
"src": "icon-512-maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
} }
], ],
"name": "Paperless-ngx", "name": "Paperless-ngx",
@@ -598,6 +598,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
self.assertEqual(input_doc.root_document_id, root.id) self.assertEqual(input_doc.root_document_id, root.id)
self.assertEqual(input_doc.source, DocumentSource.ApiUpload) self.assertEqual(input_doc.source, DocumentSource.ApiUpload)
self.assertEqual(overrides.version_label, "New Version") self.assertEqual(overrides.version_label, "New Version")
self.assertEqual(overrides.owner_id, self.user.id)
self.assertEqual(overrides.actor_id, self.user.id) self.assertEqual(overrides.actor_id, self.user.id)
def test_update_version_with_version_pk_normalizes_to_root(self) -> None: def test_update_version_with_version_pk_normalizes_to_root(self) -> None:
+1
View File
@@ -2091,6 +2091,7 @@ class DocumentViewSet(
if version_label: if version_label:
overrides.version_label = version_label.strip() overrides.version_label = version_label.strip()
if request.user is not None: if request.user is not None:
overrides.owner_id = request.user.id
overrides.actor_id = request.user.id overrides.actor_id = request.user.id
async_task = consume_file.apply_async( async_task = consume_file.apply_async(
+9 -9
View File
@@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: paperless-ngx\n" "Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-04 14:16+0000\n" "POT-Creation-Date: 2026-09-06 22:52+0000\n"
"PO-Revision-Date: 2022-02-17 04:17\n" "PO-Revision-Date: 2022-02-17 04:17\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: English\n" "Language-Team: English\n"
@@ -1628,7 +1628,7 @@ msgid "workflow runs"
msgstr "" msgstr ""
#: documents/serialisers.py:524 documents/serialisers.py:878 #: documents/serialisers.py:524 documents/serialisers.py:878
#: documents/serialisers.py:2838 documents/views.py:314 documents/views.py:2623 #: documents/serialisers.py:2838 documents/views.py:314 documents/views.py:2624
#: paperless_mail/serialisers.py:156 #: paperless_mail/serialisers.py:156
msgid "Insufficient permissions." msgid "Insufficient permissions."
msgstr "" msgstr ""
@@ -1669,7 +1669,7 @@ msgstr ""
msgid "Duplicate document identifiers are not allowed." msgid "Duplicate document identifiers are not allowed."
msgstr "" msgstr ""
#: documents/serialisers.py:2924 documents/views.py:4624 #: documents/serialisers.py:2924 documents/views.py:4625
#, python-format #, python-format
msgid "Documents not found: %(ids)s" msgid "Documents not found: %(ids)s"
msgstr "" msgstr ""
@@ -1937,7 +1937,7 @@ msgstr ""
msgid "Unable to parse URI {value}" msgid "Unable to parse URI {value}"
msgstr "" msgstr ""
#: documents/views.py:307 documents/views.py:2620 #: documents/views.py:307 documents/views.py:2621
msgid "Invalid more_like_id" msgid "Invalid more_like_id"
msgstr "" msgstr ""
@@ -1949,24 +1949,24 @@ msgstr ""
msgid "AI backend request timed out." msgid "AI backend request timed out."
msgstr "" msgstr ""
#: documents/views.py:2445 documents/views.py:2766 #: documents/views.py:2446 documents/views.py:2767
msgid "Specify only one of text, title_search, query, or more_like_id." msgid "Specify only one of text, title_search, query, or more_like_id."
msgstr "" msgstr ""
#: documents/views.py:4637 #: documents/views.py:4638
#, python-format #, python-format
msgid "Insufficient permissions to share document %(id)s." msgid "Insufficient permissions to share document %(id)s."
msgstr "" msgstr ""
#: documents/views.py:4683 #: documents/views.py:4684
msgid "Bundle is already being processed." msgid "Bundle is already being processed."
msgstr "" msgstr ""
#: documents/views.py:4747 #: documents/views.py:4748
msgid "The share link bundle is still being prepared. Please try again later." msgid "The share link bundle is still being prepared. Please try again later."
msgstr "" msgstr ""
#: documents/views.py:4761 #: documents/views.py:4762
msgid "The share link bundle is unavailable." msgid "The share link bundle is unavailable."
msgstr "" msgstr ""
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 16 KiB