Simple Managment webapp [LLM]
This commit is contained in:
@@ -48,10 +48,7 @@
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
{"input": "src/assets", "output": ".", "glob": "**/*" }
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
@@ -96,30 +93,6 @@
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ export interface MessageListResponse {
|
||||
messages: Message[];
|
||||
next_page_token: string;
|
||||
page_size: number;
|
||||
total_count: number;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
export interface SenderNameStatistics {
|
||||
name: string;
|
||||
first_timestamp: string;
|
||||
last_timestamp: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface SenderNameListResponse {
|
||||
senders: SenderNameStatistics[];
|
||||
sender_names: SenderNameStatistics[];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="login-container">
|
||||
<nz-card class="login-card">
|
||||
<div class="login-header">
|
||||
<img src="assets/logo.png" alt="SimpleCloudNotifier" class="login-logo" />
|
||||
<img src="/logo.png" alt="SimpleCloudNotifier" class="login-logo" />
|
||||
<h1>SimpleCloudNotifier</h1>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -92,26 +92,22 @@
|
||||
nzTooltipTitle="Copy"
|
||||
[appCopyToClipboard]="channel()!.subscribe_key!"
|
||||
></span>
|
||||
<span
|
||||
nz-icon
|
||||
nzType="qrcode"
|
||||
class="action-icon"
|
||||
nz-tooltip
|
||||
nzTooltipTitle="Show QR Code"
|
||||
(click)="showQrCode()"
|
||||
></span>
|
||||
</ng-template>
|
||||
<div class="key-actions">
|
||||
<button
|
||||
nz-button
|
||||
nzSize="small"
|
||||
nz-popconfirm
|
||||
nzPopconfirmTitle="Regenerate subscribe key? Existing subscribers will need the new key."
|
||||
nzPopconfirmTitle="Regenerate subscribe key? The existing key will no longer be valid."
|
||||
(nzOnConfirm)="regenerateSubscribeKey()"
|
||||
>
|
||||
Regenerate
|
||||
Invalidate & Regenerate
|
||||
</button>
|
||||
</div>
|
||||
<div class="qr-section">
|
||||
<app-qr-code-display [data]="qrCodeData()"></app-qr-code-display>
|
||||
<p class="qr-hint">Scan this QR code with the SimpleCloudNotifier app to subscribe to this channel.</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -238,15 +234,3 @@
|
||||
</ng-container>
|
||||
</nz-modal>
|
||||
|
||||
<!-- QR Code Modal -->
|
||||
<nz-modal
|
||||
[(nzVisible)]="showQrModal"
|
||||
nzTitle="Subscribe QR Code"
|
||||
(nzOnCancel)="closeQrModal()"
|
||||
[nzFooter]="null"
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<app-qr-code-display [data]="qrCodeData()"></app-qr-code-display>
|
||||
<p class="qr-hint">Scan this QR code with the SimpleCloudNotifier app to subscribe to this channel.</p>
|
||||
</ng-container>
|
||||
</nz-modal>
|
||||
|
||||
@@ -44,9 +44,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.qr-section {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
margin-bottom: 12px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
app-qr-code-display {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-hint {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
margin-top: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, inject, signal, OnInit } from '@angular/core';
|
||||
import { Component, inject, signal, computed, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -70,9 +70,20 @@ export class ChannelDetailComponent implements OnInit {
|
||||
editDescription = '';
|
||||
saving = signal(false);
|
||||
|
||||
// QR modal
|
||||
showQrModal = signal(false);
|
||||
qrCodeData = signal('');
|
||||
// QR code data (computed from channel)
|
||||
qrCodeData = computed(() => {
|
||||
const channel = this.channel();
|
||||
if (!channel || !channel.subscribe_key) return '';
|
||||
|
||||
return [
|
||||
'@scn.channel.subscribe',
|
||||
'v1',
|
||||
channel.display_name,
|
||||
channel.owner_user_id,
|
||||
channel.channel_id,
|
||||
channel.subscribe_key
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
ngOnInit(): void {
|
||||
const channelId = this.route.snapshot.paramMap.get('id');
|
||||
@@ -211,28 +222,6 @@ export class ChannelDetailComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
// QR Code
|
||||
showQrCode(): void {
|
||||
const channel = this.channel();
|
||||
if (!channel || !channel.subscribe_key) return;
|
||||
|
||||
const qrText = [
|
||||
'@scn.channel.subscribe',
|
||||
'v1',
|
||||
channel.display_name,
|
||||
channel.owner_user_id,
|
||||
channel.channel_id,
|
||||
channel.subscribe_key
|
||||
].join('\n');
|
||||
|
||||
this.qrCodeData.set(qrText);
|
||||
this.showQrModal.set(true);
|
||||
}
|
||||
|
||||
closeQrModal(): void {
|
||||
this.showQrModal.set(false);
|
||||
}
|
||||
|
||||
getSubscriptionStatus(): { label: string; color: string } {
|
||||
const channel = this.channel();
|
||||
if (!channel) return { label: 'Unknown', color: 'default' };
|
||||
|
||||
@@ -110,12 +110,14 @@
|
||||
</tbody>
|
||||
</nz-table>
|
||||
|
||||
@if (nextPageToken()) {
|
||||
<div class="load-more">
|
||||
<button nz-button nzType="default" (click)="loadMore()" [nzLoading]="loading()">
|
||||
Load More
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<div class="pagination-controls">
|
||||
<nz-pagination
|
||||
[nzPageIndex]="currentPage()"
|
||||
[nzPageSize]="pageSize"
|
||||
[nzTotal]="totalCount()"
|
||||
[nzDisabled]="loading()"
|
||||
(nzPageIndexChange)="goToPage($event)"
|
||||
></nz-pagination>
|
||||
</div>
|
||||
</nz-card>
|
||||
</div>
|
||||
|
||||
@@ -42,8 +42,17 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
.pagination-controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 16px 0;
|
||||
|
||||
.page-indicator {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
min-width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { NzEmptyModule } from 'ng-zorro-antd/empty';
|
||||
import { NzSpinModule } from 'ng-zorro-antd/spin';
|
||||
import { NzCardModule } from 'ng-zorro-antd/card';
|
||||
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
||||
import { NzPaginationModule } from 'ng-zorro-antd/pagination';
|
||||
import { ApiService } from '../../../core/services/api.service';
|
||||
import { AuthService } from '../../../core/services/auth.service';
|
||||
import { Message, MessageListParams } from '../../../core/models';
|
||||
@@ -31,6 +32,7 @@ import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe';
|
||||
NzSpinModule,
|
||||
NzCardModule,
|
||||
NzToolTipModule,
|
||||
NzPaginationModule,
|
||||
RelativeTimePipe,
|
||||
],
|
||||
templateUrl: './message-list.component.html',
|
||||
@@ -43,7 +45,11 @@ export class MessageListComponent implements OnInit {
|
||||
|
||||
messages = signal<Message[]>([]);
|
||||
loading = signal(false);
|
||||
nextPageToken = signal<string | null>(null);
|
||||
|
||||
// Pagination
|
||||
currentPage = signal(1);
|
||||
pageSize = 50;
|
||||
totalCount = signal(0);
|
||||
|
||||
// Filters
|
||||
searchText = '';
|
||||
@@ -80,11 +86,11 @@ export class MessageListComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
loadMessages(append = false): void {
|
||||
loadMessages(): void {
|
||||
this.loading.set(true);
|
||||
|
||||
const params: MessageListParams = {
|
||||
page_size: 50,
|
||||
page_size: this.pageSize,
|
||||
trimmed: true,
|
||||
};
|
||||
|
||||
@@ -97,22 +103,17 @@ export class MessageListComponent implements OnInit {
|
||||
if (this.channelFilter.length > 0) {
|
||||
params.channel = this.channelFilter.join(',');
|
||||
}
|
||||
if (append && this.nextPageToken()) {
|
||||
params.next_page_token = this.nextPageToken()!;
|
||||
|
||||
// Use page-index based pagination: $1 = page 1, $2 = page 2, etc.
|
||||
const page = this.currentPage();
|
||||
if (page > 1) {
|
||||
params.next_page_token = `$${page}`;
|
||||
}
|
||||
|
||||
this.apiService.getMessages(params).subscribe({
|
||||
next: (response) => {
|
||||
if (append) {
|
||||
this.messages.update(msgs => [...msgs, ...response.messages]);
|
||||
} else {
|
||||
this.messages.set(response.messages);
|
||||
}
|
||||
this.nextPageToken.set(
|
||||
response.next_page_token && response.next_page_token !== '@end'
|
||||
? response.next_page_token
|
||||
: null
|
||||
);
|
||||
this.messages.set(response.messages);
|
||||
this.totalCount.set(response.total_count);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
@@ -123,37 +124,44 @@ export class MessageListComponent implements OnInit {
|
||||
|
||||
applyFilters(): void {
|
||||
this.appliedSearchText = this.searchText;
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
onPriorityFilterChange(filters: string[] | null): void {
|
||||
this.priorityFilter = filters ?? [];
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
onChannelFilterChange(filters: string[] | null): void {
|
||||
this.channelFilter = filters ?? [];
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
clearSearch(): void {
|
||||
this.searchText = '';
|
||||
this.appliedSearchText = '';
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
clearChannelFilter(): void {
|
||||
this.channelFilter = [];
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
removeChannelFilter(channel: string): void {
|
||||
this.channelFilter = this.channelFilter.filter(c => c !== channel);
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
clearPriorityFilter(): void {
|
||||
this.priorityFilter = [];
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
@@ -162,6 +170,7 @@ export class MessageListComponent implements OnInit {
|
||||
this.appliedSearchText = '';
|
||||
this.channelFilter = [];
|
||||
this.priorityFilter = [];
|
||||
this.currentPage.set(1);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
@@ -175,10 +184,9 @@ export class MessageListComponent implements OnInit {
|
||||
return channel?.text?.toString() ?? internalName;
|
||||
}
|
||||
|
||||
loadMore(): void {
|
||||
if (this.nextPageToken()) {
|
||||
this.loadMessages(true);
|
||||
}
|
||||
goToPage(page: number): void {
|
||||
this.currentPage.set(page);
|
||||
this.loadMessages();
|
||||
}
|
||||
|
||||
viewMessage(message: Message): void {
|
||||
|
||||
@@ -1,50 +1,95 @@
|
||||
<div class="page-content">
|
||||
<div class="page-header">
|
||||
<h2>Senders</h2>
|
||||
<button nz-button (click)="loadSenders()">
|
||||
<button nz-button (click)="refresh()">
|
||||
<span nz-icon nzType="reload"></span>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nz-card>
|
||||
<nz-table
|
||||
#senderTable
|
||||
[nzData]="senders()"
|
||||
[nzLoading]="loading()"
|
||||
[nzShowPagination]="false"
|
||||
[nzNoResult]="noResultTpl"
|
||||
nzSize="middle"
|
||||
>
|
||||
<ng-template #noResultTpl></ng-template>
|
||||
<thead>
|
||||
<tr>
|
||||
<th nzWidth="40%">Sender Name</th>
|
||||
<th nzWidth="20%">Message Count</th>
|
||||
<th nzWidth="40%">Last Used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (sender of senders(); track sender.name) {
|
||||
<tr>
|
||||
<td>
|
||||
<span class="sender-name">{{ sender.name || '(No name)' }}</span>
|
||||
</td>
|
||||
<td>{{ sender.count }}</td>
|
||||
<td>
|
||||
<span nz-tooltip [nzTooltipTitle]="sender.last_timestamp">
|
||||
{{ sender.last_timestamp | relativeTime }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<nz-empty nzNotFoundContent="No senders found"></nz-empty>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</nz-table>
|
||||
<nz-tabset (nzSelectedIndexChange)="onTabChange($event)">
|
||||
<nz-tab nzTitle="My Senders">
|
||||
<nz-table
|
||||
#mySenderTable
|
||||
[nzData]="mySenders()"
|
||||
[nzLoading]="loadingMy()"
|
||||
[nzShowPagination]="false"
|
||||
[nzNoResult]="noResultTpl"
|
||||
nzSize="middle"
|
||||
>
|
||||
<ng-template #noResultTpl></ng-template>
|
||||
<thead>
|
||||
<tr>
|
||||
<th nzWidth="40%">Sender Name</th>
|
||||
<th nzWidth="20%">Message Count</th>
|
||||
<th nzWidth="40%">Last Used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (sender of mySenders(); track sender.name) {
|
||||
<tr>
|
||||
<td>
|
||||
<span class="sender-name">{{ sender.name || '(No name)' }}</span>
|
||||
</td>
|
||||
<td>{{ sender.count }}</td>
|
||||
<td>
|
||||
<span nz-tooltip [nzTooltipTitle]="sender.last_timestamp">
|
||||
{{ sender.last_timestamp | relativeTime }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<nz-empty nzNotFoundContent="No senders found"></nz-empty>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-tab>
|
||||
|
||||
<nz-tab nzTitle="All Senders">
|
||||
<nz-table
|
||||
#allSenderTable
|
||||
[nzData]="allSenders()"
|
||||
[nzLoading]="loadingAll()"
|
||||
[nzShowPagination]="false"
|
||||
[nzNoResult]="noResultTpl2"
|
||||
nzSize="middle"
|
||||
>
|
||||
<ng-template #noResultTpl2></ng-template>
|
||||
<thead>
|
||||
<tr>
|
||||
<th nzWidth="40%">Sender Name</th>
|
||||
<th nzWidth="20%">Message Count</th>
|
||||
<th nzWidth="40%">Last Used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (sender of allSenders(); track sender.name) {
|
||||
<tr>
|
||||
<td>
|
||||
<span class="sender-name">{{ sender.name || '(No name)' }}</span>
|
||||
</td>
|
||||
<td>{{ sender.count }}</td>
|
||||
<td>
|
||||
<span nz-tooltip [nzTooltipTitle]="sender.last_timestamp">
|
||||
{{ sender.last_timestamp | relativeTime }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<nz-empty nzNotFoundContent="No senders found"></nz-empty>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-tab>
|
||||
</nz-tabset>
|
||||
</nz-card>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,9 @@ import { NzIconModule } from 'ng-zorro-antd/icon';
|
||||
import { NzEmptyModule } from 'ng-zorro-antd/empty';
|
||||
import { NzCardModule } from 'ng-zorro-antd/card';
|
||||
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
||||
import { NzTabsModule } from 'ng-zorro-antd/tabs';
|
||||
import { ApiService } from '../../../core/services/api.service';
|
||||
import { AuthService } from '../../../core/services/auth.service';
|
||||
import { SenderNameStatistics } from '../../../core/models';
|
||||
import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe';
|
||||
|
||||
@@ -21,6 +23,7 @@ import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe';
|
||||
NzEmptyModule,
|
||||
NzCardModule,
|
||||
NzToolTipModule,
|
||||
NzTabsModule,
|
||||
RelativeTimePipe,
|
||||
],
|
||||
templateUrl: './sender-list.component.html',
|
||||
@@ -28,24 +31,61 @@ import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe';
|
||||
})
|
||||
export class SenderListComponent implements OnInit {
|
||||
private apiService = inject(ApiService);
|
||||
private authService = inject(AuthService);
|
||||
|
||||
senders = signal<SenderNameStatistics[]>([]);
|
||||
loading = signal(false);
|
||||
mySenders = signal<SenderNameStatistics[]>([]);
|
||||
allSenders = signal<SenderNameStatistics[]>([]);
|
||||
loadingMy = signal(false);
|
||||
loadingAll = signal(false);
|
||||
activeTab = signal(0);
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadSenders();
|
||||
this.loadMySenders();
|
||||
}
|
||||
|
||||
loadSenders(): void {
|
||||
this.loading.set(true);
|
||||
this.apiService.getSenderNames().subscribe({
|
||||
onTabChange(index: number): void {
|
||||
this.activeTab.set(index);
|
||||
if (index === 0 && this.mySenders().length === 0) {
|
||||
this.loadMySenders();
|
||||
} else if (index === 1 && this.allSenders().length === 0) {
|
||||
this.loadAllSenders();
|
||||
}
|
||||
}
|
||||
|
||||
loadMySenders(): void {
|
||||
const userId = this.authService.getUserId();
|
||||
if (!userId) return;
|
||||
|
||||
this.loadingMy.set(true);
|
||||
this.apiService.getUserSenderNames(userId).subscribe({
|
||||
next: (response) => {
|
||||
this.senders.set(response.senders);
|
||||
this.loading.set(false);
|
||||
this.mySenders.set(response.sender_names);
|
||||
this.loadingMy.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.loading.set(false);
|
||||
this.loadingMy.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadAllSenders(): void {
|
||||
this.loadingAll.set(true);
|
||||
this.apiService.getSenderNames().subscribe({
|
||||
next: (response) => {
|
||||
this.allSenders.set(response.sender_names);
|
||||
this.loadingAll.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.loadingAll.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
if (this.activeTab() === 0) {
|
||||
this.loadMySenders();
|
||||
} else {
|
||||
this.loadAllSenders();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
[nzCollapsedWidth]="80"
|
||||
>
|
||||
<div class="sidebar-logo">
|
||||
<img src="/logo.png" alt="SCN" class="sidebar-logo-img" />
|
||||
@if (!isCollapsed()) {
|
||||
<span>SimpleCloudNotifier</span>
|
||||
} @else {
|
||||
<span>SCN</span>
|
||||
}
|
||||
</div>
|
||||
<ul nz-menu nzTheme="dark" nzMode="inline" [nzInlineCollapsed]="isCollapsed()">
|
||||
@@ -62,7 +61,6 @@
|
||||
<span nz-icon nzType="logout"></span>
|
||||
Logout
|
||||
</button>
|
||||
<img src="assets/logo.png" alt="SCN" class="header-logo" />
|
||||
</div>
|
||||
</nz-header>
|
||||
<nz-content class="content-area">
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding: 0 16px;
|
||||
background: #001529;
|
||||
color: #fff;
|
||||
@@ -25,6 +26,12 @@
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
.sidebar-logo-img {
|
||||
height: 32px;
|
||||
width: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.app-header {
|
||||
@@ -64,11 +71,6 @@
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.header-logo {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.content-area {
|
||||
|
||||
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Reference in New Issue
Block a user