Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/build-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.*
dotnet-quality: ga
dotnet-version: 10.0.300
- name: Build Reason
env:
GITHUB_EVENT: ${{ toJson(github) }}
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.*
dotnet-quality: ga
dotnet-version: 10.0.300

- name: Version
id: version
Expand Down Expand Up @@ -78,8 +77,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.*
dotnet-quality: ga
dotnet-version: 10.0.300

- uses: actions/cache@v5
with:
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,15 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.*
dotnet-quality: ga
dotnet-version: 10.0.300

- name: Install Aspire CLI
run: |
export PATH="$HOME/.dotnet/tools:$PATH"
if dotnet tool list --global | grep -Eiq '^aspire\.cli[[:space:]]'; then
dotnet tool update --global Aspire.Cli --version 13.3.3
dotnet tool update --global Aspire.Cli --version 13.3.4
else
dotnet tool install --global Aspire.Cli --version 13.3.3
dotnet tool install --global Aspire.Cli --version 13.3.4
fi
echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
aspire --version
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/elasticsearch-docker-8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.*
dotnet-quality: ga
dotnet-version: 10.0.300
- name: Build Reason
env:
GITHUB_EVENT: ${{ toJson(github) }}
Expand Down
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:10.0.300 AS build
ARG MinVerVersionOverride
WORKDIR /app

Expand Down Expand Up @@ -40,7 +40,7 @@ RUN dotnet publish -c Release -o out --no-build

# job

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS job
FROM mcr.microsoft.com/dotnet/aspnet:10.0.8 AS job
WORKDIR /app
COPY --from=job-publish /app/src/Exceptionless.Job/out ./

Expand All @@ -57,7 +57,7 @@ RUN dotnet publish -c Release -o out --no-build /p:SkipSpaPublish=true

# api

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS api
FROM mcr.microsoft.com/dotnet/aspnet:10.0.8 AS api
WORKDIR /app
COPY --from=api-publish /app/src/Exceptionless.Web/out ./

Expand All @@ -73,7 +73,7 @@ RUN dotnet publish -c Release -o out --no-build

# app

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS app
FROM mcr.microsoft.com/dotnet/aspnet:10.0.8 AS app

WORKDIR /app
COPY --from=app-publish /app/src/Exceptionless.Web/out ./
Expand Down Expand Up @@ -147,7 +147,7 @@ USER elasticsearch

RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh && \
chmod +x dotnet-install.sh && \
./dotnet-install.sh --channel 10.0 --runtime aspnetcore && \
./dotnet-install.sh --version 10.0.8 --runtime aspnetcore && \
rm dotnet-install.sh

EXPOSE 8080 9200
Expand Down
10 changes: 5 additions & 5 deletions src/Exceptionless.AppHost/Exceptionless.AppHost.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Aspire.AppHost.Sdk/13.3.3">
<Project Sdk="Aspire.AppHost.Sdk/13.3.4">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
Expand All @@ -8,10 +8,10 @@
<NoWarn>$(NoWarn);ASPIRECERTIFICATES001</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.Azure.Storage" Version="13.3.3" />
<PackageReference Include="Aspire.Hosting.Browsers" Version="13.3.3-preview.1.26264.13" />
<PackageReference Include="Aspire.Hosting.JavaScript" Version="13.3.3" />
<PackageReference Include="Aspire.Hosting.Redis" Version="13.3.3" />
<PackageReference Include="Aspire.Hosting.Azure.Storage" Version="13.3.4" />
<PackageReference Include="Aspire.Hosting.Browsers" Version="13.3.4-preview.1.26268.8" />
<PackageReference Include="Aspire.Hosting.JavaScript" Version="13.3.4" />
<PackageReference Include="Aspire.Hosting.Redis" Version="13.3.4" />
<PackageReference Include="AspNetCore.HealthChecks.Elasticsearch" Version="9.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Exceptionless.Core.Models;
using Exceptionless.Core.Models.Billing;
using Exceptionless.Core.Repositories.Queries;
using Foundatio.Repositories;
using Foundatio.Repositories.Models;

Expand All @@ -9,6 +10,7 @@ public interface IOrganizationRepository : ISearchableRepository<Organization>
{
Task<Organization?> GetByInviteTokenAsync(string token);
Task<Organization?> GetByStripeCustomerIdAsync(string customerId);
Task<FindResults<Organization>> GetByFilterAsync(AppFilter systemFilter, string? userFilter, string? sort, CommandOptionsDescriptor<Organization>? options = null);
Task<FindResults<Organization>> GetByCriteriaAsync(string? criteria, CommandOptionsDescriptor<Organization> options, OrganizationSortBy sortBy, bool? paid = null, bool? suspended = null);
Task<BillingPlanStats> GetBillingPlanStatsAsync();
}
11 changes: 11 additions & 0 deletions src/Exceptionless.Core/Repositories/OrganizationRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Exceptionless.Core.Models;
using Exceptionless.Core.Models.Billing;
using Exceptionless.Core.Repositories.Configuration;
using Exceptionless.Core.Repositories.Queries;
using Exceptionless.Core.Validation;
using Foundatio.Repositories;
using Foundatio.Repositories.Models;
Expand Down Expand Up @@ -47,6 +48,16 @@ private void OnDocumentsChanging(object sender, DocumentsChangeEventArgs<Organiz
return hit?.Document;
}

public Task<FindResults<Organization>> GetByFilterAsync(AppFilter systemFilter, string? userFilter, string? sort, CommandOptionsDescriptor<Organization>? options = null)
{
IRepositoryQuery<Organization> query = new RepositoryQuery<Organization>()
.AppFilter(systemFilter)
.FilterExpression(userFilter);

query = !String.IsNullOrEmpty(sort) ? query.SortExpression(sort) : query.SortAscending(o => o.Name.Suffix("keyword"));
return FindAsync(q => query, options);
}

public Task<FindResults<Organization>> GetByCriteriaAsync(string? criteria, CommandOptionsDescriptor<Organization> options, OrganizationSortBy sortBy, bool? paid = null, bool? suspended = null)
{
var filter = Query<Organization>.MatchAll();
Expand Down
5 changes: 3 additions & 2 deletions src/Exceptionless.Core/Repositories/Queries/AppFilterQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,13 @@ public AppFilterQueryBuilder(AppOptions options, TimeProvider timeProvider)
return Task.CompletedTask;
}

string organizationIdFieldName = typeof(T) == typeof(Organization) ? "id" : _organizationIdFieldName;
foreach (var organization in allowedOrganizations)
{
if (shouldApplyRetentionFilter)
container |= (Query<T>.Term(_organizationIdFieldName, organization.Id) && GetRetentionFilter<T>(field, organization, _options.MaximumRetentionDays));
container |= (Query<T>.Term(organizationIdFieldName, organization.Id) && GetRetentionFilter<T>(field, organization, _options.MaximumRetentionDays));
else
container |= Query<T>.Term(_organizationIdFieldName, organization.Id);
container |= Query<T>.Term(organizationIdFieldName, organization.Id);
}

ctx.Filter &= container;
Expand Down
9 changes: 9 additions & 0 deletions src/Exceptionless.Web/ClientApp/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,15 @@
}
}

@utility no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;

&::-webkit-scrollbar {
display: none;
}
}

@keyframes accordion-down {
from {
height: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
];
</script>

<div class="bg-card text-card-foreground rounded-lg border shadow-sm {className}">
<div class="bg-card text-card-foreground rounded-lg border {className}">
{#if isLoading}
<Skeleton class="h-16 w-full rounded" />
{:else}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import DateTime from '$comp/formatters/date-time.svelte';
import TimeAgo from '$comp/formatters/time-ago.svelte';
import { Button } from '$comp/ui/button';
import { Skeleton } from '$comp/ui/skeleton';
import * as Table from '$comp/ui/table';
import * as Tabs from '$comp/ui/tabs';
Expand All @@ -14,6 +15,9 @@
import { getOrganizationQuery } from '$features/organizations/api.svelte';
import { getProjectQuery } from '$features/projects/api.svelte';
import StackCard from '$features/stacks/components/stack-card.svelte';
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import { onMount, tick } from 'svelte';

import type { PersistentEvent } from '../models/index';

Expand Down Expand Up @@ -113,6 +117,29 @@

let activeTab = $state<TabType>('Overview');
let tabs = $derived<TabType[]>(getTabs(eventQuery.data, projectQuery.data));
let tabsListRef = $state<HTMLElement | null>(null);
let canScrollTabsLeft = $state(false);
let canScrollTabsRight = $state(false);

function updateTabsOverflow(): void {
if (!tabsListRef) {
canScrollTabsLeft = false;
canScrollTabsRight = false;
return;
}

const maxScrollLeft = tabsListRef.scrollWidth - tabsListRef.clientWidth;
canScrollTabsLeft = tabsListRef.scrollLeft > 1;
canScrollTabsRight = tabsListRef.scrollLeft < maxScrollLeft - 1;
}

function scrollTabs(direction: 'left' | 'right'): void {
if (!tabsListRef) {
return;
}

tabsListRef.scrollBy({ behavior: 'smooth', left: direction === 'left' ? -tabsListRef.clientWidth / 2 : tabsListRef.clientWidth / 2 });
}

function onPromoted(title: string): void {
activeTab = title;
Expand All @@ -131,6 +158,31 @@
handleError(eventQuery.error);
}
});

$effect(() => {
const tabCount = tabs.length;
void tick().then(() => {
if (tabCount === tabs.length) {
updateTabsOverflow();
}
});
});

onMount(() => {
updateTabsOverflow();

const resizeObserver = new ResizeObserver(updateTabsOverflow);
if (tabsListRef) {
resizeObserver.observe(tabsListRef);
}

window.addEventListener('resize', updateTabsOverflow);

return () => {
resizeObserver.disconnect();
window.removeEventListener('resize', updateTabsOverflow);
};
});
</script>

<StackCard {filterChanged} id={eventQuery.data?.stack_id}></StackCard>
Expand Down Expand Up @@ -167,11 +219,39 @@

{#if eventQuery.isSuccess}
<Tabs.Root class="mt-4 mb-4" value={activeTab}>
<Tabs.List class="w-full justify-normal overflow-scroll">
{#each tabs as tab (tab)}
<Tabs.Trigger value={tab}>{tab}</Tabs.Trigger>
{/each}
</Tabs.List>
<div class="relative">
{#if canScrollTabsLeft}
<Button
aria-label="Scroll tabs left"
class="bg-background/95 absolute top-1/2 left-0 z-10 -translate-y-1/2 shadow-sm"
onclick={() => scrollTabs('left')}
size="icon-sm"
variant="outline"
>
<ChevronLeft class="size-4" />
</Button>
{/if}
<Tabs.List
bind:ref={tabsListRef}
class="no-scrollbar w-full justify-normal overflow-x-auto overflow-y-hidden scroll-smooth"
onscroll={updateTabsOverflow}
>
{#each tabs as tab (tab)}
<Tabs.Trigger class="flex-none px-3" value={tab}>{tab}</Tabs.Trigger>
{/each}
</Tabs.List>
{#if canScrollTabsRight}
<Button
aria-label="Scroll tabs right"
class="bg-background/95 absolute top-1/2 right-0 z-10 -translate-y-1/2 shadow-sm"
onclick={() => scrollTabs('right')}
size="icon-sm"
variant="outline"
>
<ChevronRight class="size-4" />
</Button>
{/if}
</div>

{#each tabs as tab (tab)}
<Tabs.Content value={tab}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
];
</script>

<div class="bg-card text-card-foreground rounded-lg border shadow-sm {className}">
<div class="bg-card text-card-foreground rounded-lg border {className}">
{#if isLoading}
<Skeleton class="h-full w-full rounded-md" />
{:else}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export interface GetOrganizationRequest {
export type GetOrganizationsMode = 'stats' | null;

export interface GetOrganizationsParams {
filter?: string;
mode: GetOrganizationsMode;
}

Expand Down Expand Up @@ -363,7 +364,7 @@ export function getOrganizationsQuery(request: GetOrganizationsRequest) {

return response;
},
queryKey: [...queryKeys.list(request.params?.mode ?? undefined), { params: request.params }]
queryKey: [...queryKeys.list(request.params?.mode ?? undefined), { params: { ...request.params } }]
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function getColumns<TOrganizations extends ViewOrganization>(mode: GetOrg
enableSorting: false,
header: 'Plan',
meta: {
class: 'w-[200px]'
class: 'w-28'
}
},
{
Expand Down Expand Up @@ -111,10 +111,10 @@ export function getColumns<TOrganizations extends ViewOrganization>(mode: GetOrg
cell: (info) => renderComponent(OrganizationsActionsCell, { organization: info.row.original }),
enableHiding: false,
enableSorting: false,
header: 'Actions',
header: '',
id: 'actions',
meta: {
class: 'w-16'
class: 'w-12 min-w-12 max-w-12 text-right'
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export function getColumns<TClientConfigurationSetting extends ClientConfigurati
cell: (info) => renderComponent(ProjectConfigActionsCell, { projectId: params.projectId, setting: info.row.original }),
enableHiding: false,
enableSorting: false,
header: 'Actions',
header: '',
id: 'actions',
meta: {
class: 'w-16'
class: 'w-12 min-w-12 max-w-12 text-right'
}
}
];
Expand Down
Loading