mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-03-20 07:55:57 +00:00
Compare commits
1 Commits
dev
...
feature-au
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f781ae0f0 |
@@ -674,9 +674,6 @@ See the corresponding [django-allauth documentation](https://docs.allauth.org/en
|
||||
for a list of provider configurations. You will also need to include the relevant Django 'application' inside the
|
||||
[PAPERLESS_APPS](#PAPERLESS_APPS) setting to activate that specific authentication provider (e.g. `allauth.socialaccount.providers.openid_connect` for the [OIDC Connect provider](https://docs.allauth.org/en/latest/socialaccount/providers/openid_connect.html)).
|
||||
|
||||
: For OpenID Connect providers, set `settings.token_auth_method` if your identity provider
|
||||
requires a specific token endpoint authentication method.
|
||||
|
||||
Defaults to None, which does not enable any third party authentication systems.
|
||||
|
||||
#### [`PAPERLESS_SOCIAL_AUTO_SIGNUP=<bool>`](#PAPERLESS_SOCIAL_AUTO_SIGNUP) {#PAPERLESS_SOCIAL_AUTO_SIGNUP}
|
||||
|
||||
@@ -103,30 +103,3 @@ Multiple options are combined in a single value:
|
||||
```bash
|
||||
PAPERLESS_DB_OPTIONS="sslmode=require;sslrootcert=/certs/ca.pem;pool.max_size=10"
|
||||
```
|
||||
|
||||
## OpenID Connect Token Endpoint Authentication
|
||||
|
||||
Some existing OpenID Connect setups may require an explicit token endpoint authentication method after upgrading to v3.
|
||||
|
||||
#### Action Required
|
||||
|
||||
If OIDC login fails at the callback with an `invalid_client` error, add `token_auth_method` to the provider `settings` in
|
||||
[`PAPERLESS_SOCIALACCOUNT_PROVIDERS`](configuration.md#PAPERLESS_SOCIALACCOUNT_PROVIDERS).
|
||||
|
||||
For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"openid_connect": {
|
||||
"APPS": [
|
||||
{
|
||||
...
|
||||
"settings": {
|
||||
"server_url": "https://login.example.com",
|
||||
"token_auth_method": "client_secret_basic"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<nav class="navbar navbar-dark fixed-top bg-primary flex-md-nowrap p-0 shadow-sm">
|
||||
<button class="navbar-toggler d-md-none collapsed border-0" type="button" data-toggle="collapse"
|
||||
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"
|
||||
(click)="isMenuCollapsed = !isMenuCollapsed">
|
||||
(click)="mobileSearchHidden = false; isMenuCollapsed = !isMenuCollapsed">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand d-flex align-items-center me-0 px-3 py-3 order-sm-0"
|
||||
@@ -24,7 +24,8 @@
|
||||
}
|
||||
</div>
|
||||
</a>
|
||||
<div class="search-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1">
|
||||
<div class="search-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1"
|
||||
[class.mobile-hidden]="mobileSearchHidden">
|
||||
<div class="col-12 col-md-7">
|
||||
<pngx-global-search></pngx-global-search>
|
||||
</div>
|
||||
@@ -378,7 +379,7 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main role="main" class="ms-sm-auto px-md-4"
|
||||
<main role="main" class="ms-sm-auto px-md-4" [class.mobile-search-hidden]="mobileSearchHidden"
|
||||
[ngClass]="slimSidebarEnabled ? 'col-slim' : 'col-md-9 col-lg-10 col-xxxl-11'">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
||||
@@ -44,6 +44,23 @@
|
||||
.sidebar {
|
||||
top: 3.5rem;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
max-height: 4.5rem;
|
||||
overflow: hidden;
|
||||
transition: max-height .2s ease, opacity .2s ease, padding-top .2s ease, padding-bottom .2s ease;
|
||||
|
||||
&.mobile-hidden {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
main.mobile-search-hidden {
|
||||
padding-top: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
|
||||
@@ -293,6 +293,58 @@ describe('AppFrameComponent', () => {
|
||||
expect(component.isMenuCollapsed).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should hide mobile search when scrolling down and show it when scrolling up', () => {
|
||||
Object.defineProperty(window, 'innerWidth', {
|
||||
configurable: true,
|
||||
value: 767,
|
||||
})
|
||||
|
||||
component.ngOnInit()
|
||||
|
||||
Object.defineProperty(window, 'scrollY', {
|
||||
configurable: true,
|
||||
value: 40,
|
||||
})
|
||||
component.onWindowScroll()
|
||||
expect(component.mobileSearchHidden).toBe(true)
|
||||
|
||||
Object.defineProperty(window, 'scrollY', {
|
||||
configurable: true,
|
||||
value: 0,
|
||||
})
|
||||
component.onWindowScroll()
|
||||
expect(component.mobileSearchHidden).toBe(false)
|
||||
})
|
||||
|
||||
it('should keep mobile search visible on desktop scroll', () => {
|
||||
Object.defineProperty(window, 'innerWidth', {
|
||||
configurable: true,
|
||||
value: 768,
|
||||
})
|
||||
component.mobileSearchHidden = true
|
||||
|
||||
component.onWindowScroll()
|
||||
|
||||
expect(component.mobileSearchHidden).toBe(false)
|
||||
})
|
||||
|
||||
it('should keep mobile search visible while the mobile menu is expanded', () => {
|
||||
Object.defineProperty(window, 'innerWidth', {
|
||||
configurable: true,
|
||||
value: 767,
|
||||
})
|
||||
component.ngOnInit()
|
||||
component.isMenuCollapsed = false
|
||||
|
||||
Object.defineProperty(window, 'scrollY', {
|
||||
configurable: true,
|
||||
value: 40,
|
||||
})
|
||||
component.onWindowScroll()
|
||||
|
||||
expect(component.mobileSearchHidden).toBe(false)
|
||||
})
|
||||
|
||||
it('should support close document & navigate on close current doc', () => {
|
||||
const closeSpy = jest.spyOn(openDocumentsService, 'closeDocument')
|
||||
closeSpy.mockReturnValue(of(true))
|
||||
|
||||
@@ -94,6 +94,14 @@ export class AppFrameComponent
|
||||
|
||||
slimSidebarAnimating: boolean = false
|
||||
|
||||
mobileSearchHidden: boolean = false
|
||||
|
||||
private lastScrollY: number = 0
|
||||
|
||||
private readonly mobileBreakpoint = 768
|
||||
|
||||
private readonly mobileSearchHideThreshold = 16
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
const permissionsService = this.permissionsService
|
||||
@@ -111,6 +119,8 @@ export class AppFrameComponent
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.lastScrollY = window.scrollY
|
||||
|
||||
if (this.settingsService.get(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED)) {
|
||||
this.checkForUpdates()
|
||||
}
|
||||
@@ -263,6 +273,37 @@ export class AppFrameComponent
|
||||
return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED)
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
onWindowResize(): void {
|
||||
if (!this.isMobileViewport()) {
|
||||
this.mobileSearchHidden = false
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:scroll')
|
||||
onWindowScroll(): void {
|
||||
const currentScrollY = window.scrollY
|
||||
|
||||
if (!this.isMobileViewport() || this.isMenuCollapsed === false) {
|
||||
this.mobileSearchHidden = false
|
||||
this.lastScrollY = currentScrollY
|
||||
return
|
||||
}
|
||||
|
||||
const delta = currentScrollY - this.lastScrollY
|
||||
|
||||
if (currentScrollY <= 0 || delta < -this.mobileSearchHideThreshold) {
|
||||
this.mobileSearchHidden = false
|
||||
} else if (
|
||||
currentScrollY > this.mobileSearchHideThreshold &&
|
||||
delta > this.mobileSearchHideThreshold
|
||||
) {
|
||||
this.mobileSearchHidden = true
|
||||
}
|
||||
|
||||
this.lastScrollY = currentScrollY
|
||||
}
|
||||
|
||||
closeMenu() {
|
||||
this.isMenuCollapsed = true
|
||||
}
|
||||
@@ -384,4 +425,8 @@ export class AppFrameComponent
|
||||
!this.settingsService.organizingSidebarSavedViews
|
||||
)
|
||||
}
|
||||
|
||||
private isMobileViewport(): boolean {
|
||||
return window.innerWidth < this.mobileBreakpoint
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +56,20 @@ $paperless-card-breakpoints: (
|
||||
|
||||
.sticky-top {
|
||||
z-index: 990; // below main navbar
|
||||
top: calc(7rem - 2px); // height of navbar (mobile)
|
||||
top: calc(7rem - 2px); // height of navbar + search row (mobile)
|
||||
transition: top 0.2s ease;
|
||||
|
||||
@media (min-width: 580px) {
|
||||
top: 3.5rem; // height of navbar
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 579.98px) {
|
||||
:host-context(main.mobile-search-hidden) .sticky-top {
|
||||
top: calc(3.5rem - 2px);
|
||||
}
|
||||
}
|
||||
|
||||
.table .form-check {
|
||||
padding: 0.2rem;
|
||||
min-height: 0;
|
||||
|
||||
Reference in New Issue
Block a user