Skip to content

Commit fda4135

Browse files
authored
Merge pull request #46 from delegateas/patch/changes-4
Minor changes
2 parents 08b19c7 + 1efbc9e commit fda4135

7 files changed

Lines changed: 84 additions & 46 deletions

File tree

Generator/DataverseService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ await Parallel.ForEachAsync(
362362

363363
private async Task<Dictionary<string, List<SecurityRole>>> GetSecurityRoles(List<Guid> rolesInSolution, Dictionary<string, SecurityPrivilegeMetadata[]> priviledges)
364364
{
365+
if (rolesInSolution.Count == 0) return [];
366+
365367
var query = new QueryExpression("role")
366368
{
367369
ColumnSet = new ColumnSet("name"),

Generator/WebsiteBuilder.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ internal void AddData()
2525
var sb = new StringBuilder();
2626
sb.AppendLine("import { GroupType } from \"@/lib/Types\";");
2727
sb.AppendLine("");
28-
sb.AppendLine($"export const LastSynched: Date = new Date('{DateTimeOffset.UtcNow:yyyy-MM-ddTHH:mm:ss.fffZ}')");
28+
sb.AppendLine($"export const LastSynched: Date = new Date('{DateTimeOffset.UtcNow:yyyy-MM-ddTHH:mm:ss.fffZ}');");
29+
var logoUrl = configuration.GetValue<string?>("Logo", defaultValue: null);
30+
var jsValue = logoUrl != null ? $"\"{logoUrl}\"" : null;
31+
sb.AppendLine($"export const Logo: string | null = {jsValue};");
32+
sb.AppendLine("");
2933
sb.AppendLine("export let Groups: GroupType[] = [");
3034
var groups = records.GroupBy(x => x.Group).OrderBy(x => x.Key);
3135
foreach (var group in groups)

Website/components/AppSidebar.tsx

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { SidebarClose, SidebarOpen } from 'lucide-react'
55
import { useIsMobile } from '@/hooks/use-mobile'
66
import SidebarNavRail from './SidebarNavRail'
77
import clsx from 'clsx'
8+
import { Logo } from '@/generated/Data'
9+
import { Separator } from './ui/separator'
810

911
interface IAppSidebarProps {}
1012

@@ -27,8 +29,8 @@ export const AppSidebar = ({}: IAppSidebarProps) => {
2729
{isMobile && (
2830
<button onClick={toggleSidebar}
2931
className={clsx(
30-
'fixed top-4 z-50 transition-all bg-white border border-gray-300 shadow rounded-full p-2',
31-
isOpen ? 'left-52' : 'left-4'
32+
'fixed top-4 z-[60] transition-all bg-white border border-gray-300 shadow rounded-full p-2',
33+
isOpen ? 'left-[272px]' : 'left-4'
3234
)}
3335
aria-label={isOpen ? 'Close Sidebar' : 'Open Sidebar'}
3436
>
@@ -39,7 +41,7 @@ export const AppSidebar = ({}: IAppSidebarProps) => {
3941
{/* Overlay for mobile sidebar */}
4042
{isMobile && isOpen && (
4143
<div
42-
className="fixed inset-0 bg-black bg-opacity-30 z-30"
44+
className="fixed inset-0 bg-black bg-opacity-30 z-[35]"
4345
onClick={toggleSidebar}
4446
aria-label="Close sidebar overlay"
4547
/>
@@ -48,7 +50,7 @@ export const AppSidebar = ({}: IAppSidebarProps) => {
4850
{/* Sidebar */}
4951
<div
5052
className={clsx(
51-
'h-screen bg-sidebar border-r border-sidebar-border z-40',
53+
'h-screen bg-sidebar border-r border-sidebar-border z-[50]',
5254
'transition-all duration-300',
5355
isMobile
5456
? [
@@ -70,12 +72,35 @@ export const AppSidebar = ({}: IAppSidebarProps) => {
7072
{/* Header */}
7173
<div className="w-full h-16 border-b border-sidebar-border p-2 flex justify-center items-center bg-white relative">
7274
{isMobile ? (
73-
<img src="/DMVLOGO.svg" alt="Logo" className="h-full" draggable={false} />
75+
<>
76+
{Logo ? (
77+
<div className='flex items-center align-center'>
78+
<img src={Logo} alt="Logo" className="h-10 w-10" draggable={false} />
79+
<Separator orientation="vertical" className="mx-2 h-6" />
80+
<img src="/DMVLOGOHORZ.svg" alt="Logo" className="h-10" draggable={false} />
81+
</div>
82+
) : (
83+
<img src="/DMVLOGOHORZ.svg" alt="Logo" className="h-10" draggable={false} />
84+
)}
85+
</>
7486
) : (
7587
showElement ? (
76-
<img src="/DMVLOGOHORZ.svg" alt="Logo" className="h-full" draggable={false} />
88+
<div className='flex items-center justify-center h-full'>
89+
{Logo ? (
90+
<div className='flex items-center align-center'>
91+
<img src={Logo} alt="Logo" className="h-10 w-10" draggable={false} />
92+
<Separator orientation="vertical" className="mx-2 h-6" />
93+
<img src="/DMVLOGOHORZ.svg" alt="Logo" className="h-10" draggable={false} />
94+
</div>
95+
) : (
96+
<img src="/DMVLOGOHORZ.svg" alt="Logo" className="h-10" draggable={false} />
97+
)}
98+
</div>
7799
) : (
78-
<img src="/DMVLOGO.svg" alt="Logo" className="h-full" draggable={false} />
100+
<div className="relative w-full h-full flex items-center justify-center">
101+
<img src="/DMVLOGO.svg" alt="Logo" className="h-full" draggable={false} />
102+
{ Logo && <img src={Logo} className='absolute rounded-md shadow-sm border border-blue-500 -bottom-1 -right-1 h-6 w-6 p-1 bg-white' /> }
103+
</div>
79104
)
80105
)}
81106
</div>
@@ -84,7 +109,7 @@ export const AppSidebar = ({}: IAppSidebarProps) => {
84109
{!isMobile && (
85110
<button
86111
onClick={toggleElement}
87-
className="absolute right-0 top-1/2 -translate-y-1/2 w-4 h-12 bg-gray-50 border border-gray-300 shadow rounded-sm flex items-center justify-center z-50 hover:bg-blue-50"
112+
className="absolute right-0 top-1/2 -translate-y-1/2 w-4 h-12 bg-gray-50 border border-gray-300 shadow rounded-sm flex items-center justify-center z-[60] hover:bg-blue-50"
88113
style={{ marginRight: '-12px' }}
89114
aria-label={showElement ? 'Hide Details' : 'Show Details'}
90115
>

Website/components/datamodelview/TimeSlicedSearch.tsx

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import React, { useState, useRef, useCallback, useEffect } from 'react';
44
import { createPortal } from 'react-dom';
55
import { Input } from '../ui/input';
6-
import { Search, ChevronUp, ChevronDown } from 'lucide-react';
6+
import { Search, ChevronUp, ChevronDown, X } from 'lucide-react';
7+
import { useSidebar } from '@/contexts/SidebarContext';
8+
import { useIsMobile } from '@/hooks/use-mobile';
79

810
interface TimeSlicedSearchProps {
911
onSearch: (value: string) => void;
@@ -28,11 +30,16 @@ export const TimeSlicedSearch = ({
2830
const [localValue, setLocalValue] = useState('');
2931
const [isTyping, setIsTyping] = useState(false);
3032
const [portalRoot, setPortalRoot] = useState<HTMLElement | null>(null);
33+
const { isOpen } = useSidebar();
34+
const isMobile = useIsMobile();
3135

3236
const searchTimeoutRef = useRef<number>();
3337
const typingTimeoutRef = useRef<number>();
3438
const frameRef = useRef<number>();
3539

40+
// Hide search on mobile when sidebar is open
41+
const shouldHideSearch = isMobile && isOpen;
42+
3643
// Time-sliced debouncing using requestAnimationFrame
3744
const scheduleSearch = useCallback((value: string) => {
3845
if (searchTimeoutRef.current) {
@@ -81,6 +88,22 @@ export const TimeSlicedSearch = ({
8188

8289
}, [isTyping, onLoadingChange, scheduleSearch]);
8390

91+
// Handle clear button
92+
const handleClear = useCallback(() => {
93+
setLocalValue('');
94+
onSearch(''); // Clear search immediately
95+
setIsTyping(false);
96+
onLoadingChange(false);
97+
98+
// Clear any pending timeouts
99+
if (searchTimeoutRef.current) {
100+
clearTimeout(searchTimeoutRef.current);
101+
}
102+
if (typingTimeoutRef.current) {
103+
clearTimeout(typingTimeoutRef.current);
104+
}
105+
}, [onSearch, onLoadingChange]);
106+
84107
// Handle keyboard navigation
85108
const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
86109
if (e.key === 'Enter' && !e.shiftKey) {
@@ -151,7 +174,7 @@ export const TimeSlicedSearch = ({
151174
}, []);
152175

153176
const searchInput = (
154-
<div className="fixed top-4 right-8 z-50 w-80">
177+
<div className={`fixed top-4 right-8 z-50 w-[280px] transition-opacity duration-200 ${shouldHideSearch ? 'opacity-0 pointer-events-none' : 'opacity-100'}`}>
155178
{/* Search Input Container */}
156179
<div className="flex items-center gap-2">
157180
<div className="relative flex-1">
@@ -163,16 +186,26 @@ export const TimeSlicedSearch = ({
163186
value={localValue}
164187
onChange={handleChange}
165188
onKeyDown={handleKeyDown}
166-
className="pl-10 pr-8 h-9 text-sm"
189+
className="pl-10 pr-10 h-9 text-sm"
167190
spellCheck={false}
168191
autoComplete="off"
169192
autoCapitalize="off"
170193
/>
171-
{isTyping && (
172-
<div className="absolute right-3 top-1/2 transform -translate-y-1/2">
194+
{/* Clear button or loading indicator */}
195+
<div className="absolute right-3 top-1/2 transform -translate-y-1/2 flex justify-center items-center">
196+
{isTyping ? (
173197
<div className="w-4 h-4 border-2 border-blue-400 border-t-transparent rounded-full animate-spin"></div>
174-
</div>
175-
)}
198+
) : localValue ? (
199+
<button
200+
onClick={handleClear}
201+
className="w-4 h-4 text-gray-400 hover:text-gray-600 transition-colors"
202+
title="Clear search"
203+
aria-label="Clear search"
204+
>
205+
<X className="w-4 h-4" />
206+
</button>
207+
) : null}
208+
</div>
176209
</div>
177210

178211
{/* Navigation Buttons */}

Website/stubs/Data.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
/// This file is a stub and should not be modified directly.
33

44
import { GroupType } from "@/lib/Types";
5-
export const LastSynched: Date = new Date()
5+
6+
export const LastSynched: Date = new Date();
7+
export const Logo: string | null = null;
8+
69
export let Groups: GroupType[] = [
710
{
811
"Name":"Untitled",

package-lock.json

Lines changed: 0 additions & 24 deletions
This file was deleted.

package.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)