Merge branch 'v23.02-branch' into development
This commit is contained in:
		
						commit
						50f3c10f19
					
				| 
						 | 
				
			
			@ -311,3 +311,12 @@ m4tthi4s :: French
 | 
			
		|||
toras9000 :: Japanese
 | 
			
		||||
pathab :: German
 | 
			
		||||
MichelSchoon85 :: Dutch
 | 
			
		||||
Jøran Haugli (haugli92) :: Norwegian Bokmal
 | 
			
		||||
Vasileios Kouvelis (VasilisKouvelis) :: Greek
 | 
			
		||||
Dremski :: Bulgarian
 | 
			
		||||
Frédéric SENE (nothingfr) :: French
 | 
			
		||||
bendem :: French
 | 
			
		||||
kostasdizas :: Greek
 | 
			
		||||
Ricardo Schroeder (brownstone666) :: Portuguese, Brazilian
 | 
			
		||||
Eitan MG (EitanMG) :: Hebrew
 | 
			
		||||
Robin Flikkema (RobinFlikkema) :: Dutch
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,9 @@ use Illuminate\Support\Facades\DB;
 | 
			
		|||
 | 
			
		||||
class TagRepo
 | 
			
		||||
{
 | 
			
		||||
    protected PermissionApplicator $permissions;
 | 
			
		||||
 | 
			
		||||
    public function __construct(PermissionApplicator $permissions)
 | 
			
		||||
    {
 | 
			
		||||
        $this->permissions = $permissions;
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected PermissionApplicator $permissions
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +88,7 @@ class TagRepo
 | 
			
		|||
    {
 | 
			
		||||
        $query = Tag::query()
 | 
			
		||||
            ->select('*', DB::raw('count(*) as count'))
 | 
			
		||||
            ->where('value', '!=', '')
 | 
			
		||||
            ->groupBy('value');
 | 
			
		||||
 | 
			
		||||
        if ($searchTerm) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,11 +8,9 @@ use Illuminate\Http\Request;
 | 
			
		|||
 | 
			
		||||
class TagController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    protected TagRepo $tagRepo;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TagRepo $tagRepo)
 | 
			
		||||
    {
 | 
			
		||||
        $this->tagRepo = $tagRepo;
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected TagRepo $tagRepo
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,7 +197,7 @@ class UserController extends Controller
 | 
			
		|||
        $this->checkPermissionOrCurrentUser('users-manage', $id);
 | 
			
		||||
 | 
			
		||||
        $user = $this->userRepo->getById($id);
 | 
			
		||||
        $newOwnerId = $request->get('new_owner_id', null);
 | 
			
		||||
        $newOwnerId = intval($request->get('new_owner_id')) ?: null;
 | 
			
		||||
 | 
			
		||||
        $this->userRepo->destroy($user, $newOwnerId);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import {escapeHtml} from "../services/util";
 | 
			
		||||
import {onChildEvent} from "../services/dom";
 | 
			
		||||
import {Component} from "./component";
 | 
			
		||||
import {KeyboardNavigationHandler} from "../services/keyboard-navigation";
 | 
			
		||||
 | 
			
		||||
const ajaxCache = {};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,26 +22,31 @@ export class AutoSuggest extends Component {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    setupListeners() {
 | 
			
		||||
        const navHandler = new KeyboardNavigationHandler(
 | 
			
		||||
            this.list,
 | 
			
		||||
            event => {
 | 
			
		||||
                this.input.focus();
 | 
			
		||||
                setTimeout(() => this.hideSuggestions(), 1);
 | 
			
		||||
            },
 | 
			
		||||
            event => {
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                this.selectSuggestion(event.target.textContent);
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
        navHandler.shareHandlingToEl(this.input);
 | 
			
		||||
 | 
			
		||||
        onChildEvent(this.list, '.text-item', 'click', (event, el) => {
 | 
			
		||||
            this.selectSuggestion(el.textContent);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.input.addEventListener('input', this.requestSuggestions.bind(this));
 | 
			
		||||
        this.input.addEventListener('focus', this.requestSuggestions.bind(this));
 | 
			
		||||
        this.input.addEventListener('blur', this.hideSuggestionsIfFocusedLost.bind(this));
 | 
			
		||||
        this.input.addEventListener('keydown', event => {
 | 
			
		||||
            if (event.key === 'Tab') {
 | 
			
		||||
                this.hideSuggestions();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.input.addEventListener('blur', this.hideSuggestionsIfFocusedLost.bind(this));
 | 
			
		||||
        this.container.addEventListener('keydown', this.containerKeyDown.bind(this));
 | 
			
		||||
 | 
			
		||||
        onChildEvent(this.list, 'button', 'click', (event, el) => {
 | 
			
		||||
            this.selectSuggestion(el.textContent);
 | 
			
		||||
        });
 | 
			
		||||
        onChildEvent(this.list, 'button', 'keydown', (event, el) => {
 | 
			
		||||
            if (event.key === 'Enter') {
 | 
			
		||||
                this.selectSuggestion(el.textContent);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    selectSuggestion(value) {
 | 
			
		||||
| 
						 | 
				
			
			@ -52,36 +58,6 @@ export class AutoSuggest extends Component {
 | 
			
		|||
        this.hideSuggestions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    containerKeyDown(event) {
 | 
			
		||||
        if (event.key === 'Enter') event.preventDefault();
 | 
			
		||||
        if (this.list.classList.contains('hidden')) return;
 | 
			
		||||
 | 
			
		||||
        // Down arrow
 | 
			
		||||
        if (event.key === 'ArrowDown') {
 | 
			
		||||
            this.moveFocus(true);
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
        // Up Arrow
 | 
			
		||||
        else if (event.key === 'ArrowUp') {
 | 
			
		||||
            this.moveFocus(false);
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
        // Escape key
 | 
			
		||||
        else if (event.key === 'Escape') {
 | 
			
		||||
            this.hideSuggestions();
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    moveFocus(forward = true) {
 | 
			
		||||
        const focusables = Array.from(this.container.querySelectorAll('input,button'));
 | 
			
		||||
        const index = focusables.indexOf(document.activeElement);
 | 
			
		||||
        const newFocus = focusables[index + (forward ? 1 : -1)];
 | 
			
		||||
        if (newFocus) {
 | 
			
		||||
            newFocus.focus()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async requestSuggestions() {
 | 
			
		||||
        if (Date.now() - this.lastPopulated < 50) {
 | 
			
		||||
            return;
 | 
			
		||||
| 
						 | 
				
			
			@ -132,9 +108,11 @@ export class AutoSuggest extends Component {
 | 
			
		|||
            return this.hideSuggestions();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.list.innerHTML = suggestions.map(value => `<li><button type="button" class="text-item">${escapeHtml(value)}</button></li>`).join('');
 | 
			
		||||
        // This used to use <button>s but was changed to div elements since Safari would not focus on buttons
 | 
			
		||||
        // on which causes a range of other complexities related to focus handling.
 | 
			
		||||
        this.list.innerHTML = suggestions.map(value => `<li><div tabindex="0" class="text-item">${escapeHtml(value)}</div></li>`).join('');
 | 
			
		||||
        this.list.style.display = 'block';
 | 
			
		||||
        for (const button of this.list.querySelectorAll('button')) {
 | 
			
		||||
        for (const button of this.list.querySelectorAll('.text-item')) {
 | 
			
		||||
            button.addEventListener('blur', this.hideSuggestionsIfFocusedLost.bind(this));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,6 +162,16 @@ class UserManagementTest extends TestCase
 | 
			
		|||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_delete_with_empty_owner_migration_id_works()
 | 
			
		||||
    {
 | 
			
		||||
        $user = $this->users->editor();
 | 
			
		||||
 | 
			
		||||
        $resp = $this->asAdmin()->delete("settings/users/{$user->id}", ['new_owner_id' => '']);
 | 
			
		||||
        $resp->assertRedirect('/settings/users');
 | 
			
		||||
        $this->assertActivityExists(ActivityType::USER_DELETE);
 | 
			
		||||
        $this->assertSessionHas('success');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_delete_removes_user_preferences()
 | 
			
		||||
    {
 | 
			
		||||
        $editor = $this->users->editor();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue