From 19e17c85fa7564e7910b64a7f0309b2c41899a9d Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Fri, 4 Feb 2022 11:28:58 -0800 Subject: [PATCH] Misc Fixes (#1031) * Changed the default margin for mobile in book reader to 5% * Fixed a bug where checking for update did no current version validation before sending the update to the UI. * Added some documentation to the book code * Changed token expiry to 2 weeks. * Search bar will by default not have a border outline * Cleaned up some styles for white mode hovering on search * Added missing genre search group, reworked some clearing code, fixed click handlers * Fixed genre property * Changed the series title to show bookmarks and the edit button will now take you to series * Fixed up accordion tabpanel color in dark mode * Fixed a typo of CoverArtist instead of "Cover artist" * Added some documentation changes * Fixed a bug where sort options on All-Series wasn't working * Added a thanks to Palace-Designs who hosts our infrastructure to the readme. * Fixed a bug where duplicate people for the same role would be returned * Fixed a bug where when user cleared out input manually, search would retain old search results --- API/Controllers/BookController.cs | 13 ++++-- API/Controllers/ServerController.cs | 9 ++-- API/Data/Repositories/SeriesRepository.cs | 6 +-- API/Services/BookService.cs | 5 +++ API/Services/Tasks/VersionUpdaterService.cs | 10 +++-- API/Services/TokenService.cs | 2 +- Logo/hosting-sponsor.png | Bin 0 -> 12894 bytes README.md | 8 +++- UI/Web/src/app/_services/metadata.service.ts | 12 +++--- .../book-reader/book-reader.component.ts | 2 +- .../card-detail-layout.component.html | 1 - .../card-detail-layout.component.ts | 2 +- .../grouped-typeahead.component.html | 12 +++++- .../grouped-typeahead.component.scss | 39 ++++++++++++++---- .../grouped-typeahead.component.ts | 8 +++- .../app/nav-header/nav-header.component.html | 16 +++++-- .../app/nav-header/nav-header.component.ts | 20 +++++---- UI/Web/src/app/person-role.pipe.ts | 2 +- .../src/app/typeahead/typeahead-settings.ts | 2 +- .../series-bookmarks.component.html | 6 +-- UI/Web/src/assets/themes/dark.scss | 6 +++ UI/Web/src/theme/_colors.scss | 4 ++ 22 files changed, 130 insertions(+), 55 deletions(-) create mode 100644 Logo/hosting-sponsor.png diff --git a/API/Controllers/BookController.cs b/API/Controllers/BookController.cs index 2bca8bb2f..521c763d4 100644 --- a/API/Controllers/BookController.cs +++ b/API/Controllers/BookController.cs @@ -77,11 +77,16 @@ namespace API.Controllers return File(content, contentType, $"{chapterId}-{file}"); } + /// + /// This will return a list of mappings from ID -> page num. ID will be the xhtml key and page num will be the reading order + /// this is used to rewrite anchors in the book text so that we always load properly in FE + /// + /// This is essentially building the table of contents + /// + /// [HttpGet("{chapterId}/chapters")] public async Task>> GetBookChapters(int chapterId) { - // This will return a list of mappings from ID -> pagenum. ID will be the xhtml key and pagenum will be the reading order - // this is used to rewrite anchors in the book text so that we always load properly in FE var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId); using var book = await EpubReader.OpenBookAsync(chapter.Files.ElementAt(0).FilePath); var mappings = await _bookService.CreateKeyToPageMappingAsync(book); @@ -126,7 +131,7 @@ namespace API.Controllers var tocPage = book.Content.Html.Keys.FirstOrDefault(k => k.ToUpper().Contains("TOC")); if (tocPage == null) return Ok(chaptersList); - // Find all anchor tags, for each anchor we get inner text, to lower then titlecase on UI. Get href and generate page content + // Find all anchor tags, for each anchor we get inner text, to lower then title case on UI. Get href and generate page content var doc = new HtmlDocument(); var content = await book.Content.Html[tocPage].ReadContentAsync(); doc.LoadHtml(content); @@ -252,7 +257,7 @@ namespace API.Controllers return BadRequest("Could not find the appropriate html for that page"); } - private void LogBookErrors(EpubBookRef book, EpubTextContentFileRef contentFileRef, HtmlDocument doc) + private void LogBookErrors(EpubBookRef book, EpubContentFileRef contentFileRef, HtmlDocument doc) { _logger.LogError("{FilePath} has an invalid html file (Page {PageName})", book.FilePath, contentFileRef.FileName); foreach (var error in doc.ParseErrors) diff --git a/API/Controllers/ServerController.cs b/API/Controllers/ServerController.cs index 0f2124d06..8b5cc80c8 100644 --- a/API/Controllers/ServerController.cs +++ b/API/Controllers/ServerController.cs @@ -25,22 +25,20 @@ namespace API.Controllers private readonly IConfiguration _config; private readonly IBackupService _backupService; private readonly IArchiveService _archiveService; - private readonly ICacheService _cacheService; private readonly IVersionUpdaterService _versionUpdaterService; private readonly IStatsService _statsService; private readonly ICleanupService _cleanupService; private readonly IEmailService _emailService; public ServerController(IHostApplicationLifetime applicationLifetime, ILogger logger, IConfiguration config, - IBackupService backupService, IArchiveService archiveService, ICacheService cacheService, - IVersionUpdaterService versionUpdaterService, IStatsService statsService, ICleanupService cleanupService, IEmailService emailService) + IBackupService backupService, IArchiveService archiveService, IVersionUpdaterService versionUpdaterService, IStatsService statsService, + ICleanupService cleanupService, IEmailService emailService) { _applicationLifetime = applicationLifetime; _logger = logger; _config = config; _backupService = backupService; _archiveService = archiveService; - _cacheService = cacheService; _versionUpdaterService = versionUpdaterService; _statsService = statsService; _cleanupService = cleanupService; @@ -111,6 +109,9 @@ namespace API.Controllers } } + /// + /// Checks for updates, if no updates that are > current version installed, returns null + /// [HttpGet("check-update")] public async Task> CheckForUpdates() { diff --git a/API/Data/Repositories/SeriesRepository.cs b/API/Data/Repositories/SeriesRepository.cs index 4fa0690aa..1aad6b349 100644 --- a/API/Data/Repositories/SeriesRepository.cs +++ b/API/Data/Repositories/SeriesRepository.cs @@ -240,11 +240,6 @@ public class SeriesRepository : ISeriesRepository { var query = await CreateFilteredSearchQueryable(userId, libraryId, filter); - if (filter.SortOptions == null) - { - query = query.OrderBy(s => s.SortName); - } - var retSeries = query .ProjectTo(_mapper.ConfigurationProvider) .AsSplitQuery() @@ -314,6 +309,7 @@ public class SeriesRepository : ISeriesRepository .Where(sm => seriesIds.Contains(sm.SeriesId)) .SelectMany(sm => sm.People.Where(t => EF.Functions.Like(t.Name, $"%{searchQuery}%"))) .AsSplitQuery() + .Distinct() .ProjectTo(_mapper.ConfigurationProvider) .ToListAsync(); diff --git a/API/Services/BookService.cs b/API/Services/BookService.cs index 5d40437d3..0b59e109d 100644 --- a/API/Services/BookService.cs +++ b/API/Services/BookService.cs @@ -458,6 +458,11 @@ namespace API.Services return content; } + /// + /// Removes the leading ../ + /// + /// + /// public static string CleanContentKeys(string key) { return key.Replace("../", string.Empty); diff --git a/API/Services/Tasks/VersionUpdaterService.cs b/API/Services/Tasks/VersionUpdaterService.cs index 4b341ba36..255d0b105 100644 --- a/API/Services/Tasks/VersionUpdaterService.cs +++ b/API/Services/Tasks/VersionUpdaterService.cs @@ -57,8 +57,8 @@ public class VersionUpdaterService : IVersionUpdaterService private readonly IPresenceTracker _tracker; private readonly Markdown _markdown = new MarkdownDeep.Markdown(); #pragma warning disable S1075 - private static readonly string GithubLatestReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases/latest"; - private static readonly string GithubAllReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases"; + private const string GithubLatestReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases/latest"; + private const string GithubAllReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases"; #pragma warning restore S1075 public VersionUpdaterService(ILogger logger, IHubContext messageHub, IPresenceTracker tracker) @@ -76,10 +76,12 @@ public class VersionUpdaterService : IVersionUpdaterService /// /// Fetches the latest release from Github /// - public async Task CheckForUpdate() + /// Latest update or null if current version is greater than latest update + public async Task CheckForUpdate() { var update = await GetGithubRelease(); - return CreateDto(update); + var dto = CreateDto(update); + return new Version(dto.UpdateVersion) <= new Version(dto.CurrentVersion) ? null : dto; } public async Task> GetAllReleases() diff --git a/API/Services/TokenService.cs b/API/Services/TokenService.cs index ffd3c9429..4b734e8b9 100644 --- a/API/Services/TokenService.cs +++ b/API/Services/TokenService.cs @@ -50,7 +50,7 @@ public class TokenService : ITokenService var tokenDescriptor = new SecurityTokenDescriptor() { Subject = new ClaimsIdentity(claims), - Expires = DateTime.Now.AddDays(7), + Expires = DateTime.Now.AddDays(14), SigningCredentials = creds }; diff --git a/Logo/hosting-sponsor.png b/Logo/hosting-sponsor.png new file mode 100644 index 0000000000000000000000000000000000000000..81c0b3d786c726684a603afbd317e40a4c166c6d GIT binary patch literal 12894 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 JetBrains](http: * [ Rider](http://www.jetbrains.com/rider/) * [ dotTrace](http://www.jetbrains.com/dottrace/) +## Palace-Designs +We would like to extend a big thank you to [](https://www.palace-designs.com/) who hosts our infrastructure pro-bono. + + ### License * [GNU GPL v3](http://www.gnu.org/licenses/gpl.html) -* Copyright 2020-2021 +* Copyright 2020-2022 diff --git a/UI/Web/src/app/_services/metadata.service.ts b/UI/Web/src/app/_services/metadata.service.ts index 4d64a7920..97d39624b 100644 --- a/UI/Web/src/app/_services/metadata.service.ts +++ b/UI/Web/src/app/_services/metadata.service.ts @@ -42,7 +42,7 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get>(this.baseUrl + method);; + return this.httpClient.get>(this.baseUrl + method); } getAllPublicationStatus(libraries?: Array) { @@ -50,7 +50,7 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get>(this.baseUrl + method);; + return this.httpClient.get>(this.baseUrl + method); } getAllTags(libraries?: Array) { @@ -58,7 +58,7 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get>(this.baseUrl + method);; + return this.httpClient.get>(this.baseUrl + method); } getAllGenres(libraries?: Array) { @@ -66,7 +66,7 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get(this.baseUrl + method); + return this.httpClient.get>(this.baseUrl + method); } getAllLanguages(libraries?: Array) { @@ -74,7 +74,7 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get(this.baseUrl + method); + return this.httpClient.get>(this.baseUrl + method); } getAllPeople(libraries?: Array) { @@ -82,6 +82,6 @@ export class MetadataService { if (libraries != undefined && libraries.length > 0) { method += '?libraryIds=' + libraries.join(','); } - return this.httpClient.get(this.baseUrl + method); + return this.httpClient.get>(this.baseUrl + method); } } diff --git a/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts b/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts index be34ac510..0e474968a 100644 --- a/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts +++ b/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts @@ -615,7 +615,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy { let margin = '15%'; if (windowWidth <= 700) { - margin = '0%'; + margin = '5%'; } if (this.user) { if (windowWidth > 700) { diff --git a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html index ae5d6c414..19626e296 100644 --- a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html +++ b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html @@ -5,7 +5,6 @@   {{header}}  - {{pagination.totalItems}} diff --git a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts index ab3ec7df6..79e9be68e 100644 --- a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts +++ b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts @@ -367,7 +367,7 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy { }; this.collectionSettings.compareFn = (options: CollectionTag[], filter: string) => { const f = filter.toLowerCase(); - return options.filter(m => m.title.toLowerCase() === f); + return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter)); } if (this.filterSettings.presets?.collectionTags && this.filterSettings.presets?.collectionTags.length > 0) { diff --git a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.html b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.html index f9871106d..264d7e732 100644 --- a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.html +++ b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.html @@ -35,6 +35,16 @@ + +
  • Genres
  • +
      +
    • + +
    • +
    +
    +
  • Tags
    • @@ -46,7 +56,7 @@ -
    • Tags
    • +
    • People
      • diff --git a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.scss b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.scss index b3e7d3021..dec2c2f3b 100644 --- a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.scss +++ b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.scss @@ -15,8 +15,10 @@ input { width: 100% !important; } + .typeahead-input { - border: 1px solid #ccc; + border: 1px solid transparent; + border-radius: 4px; padding: 0px 6px; display: inline-block; overflow: hidden; @@ -24,7 +26,6 @@ input { z-index: 1; box-sizing: border-box; box-shadow: none; - border-radius: 4px; cursor: text; background-color: #fff; min-height: 38px; @@ -32,6 +33,7 @@ input { transition-duration: 0.3s; display: block; + .close { cursor: pointer; position: absolute; @@ -67,6 +69,7 @@ input { .typeahead-input.focused { width: 100%; + border-color: #ccc; } /* small devices (phones, 650px and down) */ @@ -117,7 +120,6 @@ input { flex: auto; max-height: calc(100vh - 58px); height: fit-content; - //background-color: colors.$dark-bg-color; } .list-group.results { @@ -149,13 +151,34 @@ ul ul { cursor: pointer; } -.section-header { - background: colors.$dark-item-accent-bg; - cursor: default; +::ng-deep .bg-dark { + & .section-header { + + background: colors.$dark-item-accent-bg; + cursor: default; + } + + & .section-header:hover { + background-color: colors.$dark-item-accent-bg !important; + } } -.section-header:hover { - background-color: colors.$dark-item-accent-bg !important; +::ng-deep .bg-light { + & .section-header { + + background: colors.$white-item-accent-bg; + cursor: default; + } + + & .section-header:hover, .list-group-item.section-header:hover { + background: colors.$white-item-accent-bg !important; + } + + & .list-group-item:hover { + background-color: colors.$primary-color !important; + } + + } .spinner-border { diff --git a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.ts b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.ts index 385c0d87e..030a6e720 100644 --- a/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.ts +++ b/UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.ts @@ -56,6 +56,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy { @ContentChild('collectionTemplate') collectionTemplate: TemplateRef | undefined; @ContentChild('tagTemplate') tagTemplate: TemplateRef | undefined; @ContentChild('personTemplate') personTemplate: TemplateRef | undefined; + @ContentChild('genreTemplate') genreTemplate!: TemplateRef; @ContentChild('noResultsTemplate') noResultsTemplate!: TemplateRef; @@ -147,6 +148,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy { } resetField() { + this.prevSearchTerm = ''; this.typeaheadForm.get('typeahead')?.setValue(this.initialValue); this.clearField.emit(); } @@ -159,6 +161,9 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy { return; } } + if (this.searchTerm === '') { + this.resetField(); + } this.hasFocus = false; this.focusChanged.emit(this.hasFocus); } @@ -169,7 +174,8 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy { } public clear() { - this.resetField(); + this.prevSearchTerm = ''; + this.typeaheadForm.get('typeahead')?.setValue(this.initialValue); } } diff --git a/UI/Web/src/app/nav-header/nav-header.component.html b/UI/Web/src/app/nav-header/nav-header.component.html index 9258dff24..56c5d2518 100644 --- a/UI/Web/src/app/nav-header/nav-header.component.html +++ b/UI/Web/src/app/nav-header/nav-header.component.html @@ -23,7 +23,7 @@ > -
        +
        @@ -39,7 +39,7 @@ -
        +
        @@ -50,7 +50,7 @@ -
        +
        @@ -58,7 +58,7 @@ -
        +
        @@ -67,6 +67,14 @@
        + +
        +
        +
        +
        +
        +
        + No results found diff --git a/UI/Web/src/app/nav-header/nav-header.component.ts b/UI/Web/src/app/nav-header/nav-header.component.ts index 4a8e459e1..ebf7318a9 100644 --- a/UI/Web/src/app/nav-header/nav-header.component.ts +++ b/UI/Web/src/app/nav-header/nav-header.component.ts @@ -3,8 +3,8 @@ import { Component, HostListener, Inject, OnDestroy, OnInit, ViewChild } from '@ import { Router } from '@angular/router'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { isTemplateSpan } from 'typescript'; import { ScrollService } from '../scroll.service'; +import { CollectionTag } from '../_models/collection-tag'; import { PersonRole } from '../_models/person'; import { SearchResult } from '../_models/search-result'; import { SearchResultGroup } from '../_models/search/search-result-group'; @@ -104,11 +104,13 @@ export class NavHeaderComponent implements OnInit, OnDestroy { let params: any = {}; params[queryParamName] = filter; params['page'] = 1; + this.clearSearch(); this.router.navigate(['all-series'], {queryParams: params}); } goToPerson(role: PersonRole, filter: any) { // TODO: Move this to utility service + this.clearSearch(); switch(role) { case PersonRole.Artist: this.goTo('artist', filter); @@ -147,19 +149,24 @@ export class NavHeaderComponent implements OnInit, OnDestroy { } clearSearch() { + this.searchViewRef.clear(); + this.searchTerm = ''; this.searchResults = new SearchResultGroup(); } - clickSearchResult(item: SearchResult) { - console.log('Click occured'); + clickSeriesSearchResult(item: SearchResult) { + this.clearSearch(); const libraryId = item.libraryId; const seriesId = item.seriesId; - this.searchViewRef.clear(); - this.searchResults.reset(); - this.searchTerm = ''; this.router.navigate(['library', libraryId, 'series', seriesId]); } + clickCollectionSearchResult(item: CollectionTag) { + this.clearSearch(); + this.router.navigate(['collections', item.id]); + } + + scrollToTop() { window.scroll({ top: 0, @@ -168,7 +175,6 @@ export class NavHeaderComponent implements OnInit, OnDestroy { } focusUpdate(searchFocused: boolean) { - console.log('search has focus', searchFocused); this.searchFocused = searchFocused return searchFocused; } diff --git a/UI/Web/src/app/person-role.pipe.ts b/UI/Web/src/app/person-role.pipe.ts index 69190fcf6..9559e4ad6 100644 --- a/UI/Web/src/app/person-role.pipe.ts +++ b/UI/Web/src/app/person-role.pipe.ts @@ -11,7 +11,7 @@ export class PersonRolePipe implements PipeTransform { case PersonRole.Artist: return 'Artist'; case PersonRole.Character: return 'Character'; case PersonRole.Colorist: return 'Colorist'; - case PersonRole.CoverArtist: return 'CoverArtist'; + case PersonRole.CoverArtist: return 'Cover Artist'; case PersonRole.Editor: return 'Editor'; case PersonRole.Inker: return 'Inker'; case PersonRole.Letterer: return 'Letterer'; diff --git a/UI/Web/src/app/typeahead/typeahead-settings.ts b/UI/Web/src/app/typeahead/typeahead-settings.ts index 9fc3b28e8..7e531bf84 100644 --- a/UI/Web/src/app/typeahead/typeahead-settings.ts +++ b/UI/Web/src/app/typeahead/typeahead-settings.ts @@ -22,7 +22,7 @@ export class TypeaheadSettings { */ savedData!: T[] | T; /** - * Function to compare the elements. Should return all elements that fit the matching criteria. + * Function to compare the elements. Should return all elements that fit the matching criteria. This is only used with non-Observable based fetchFn, but must be defined for all uses of typeahead (TODO) */ compareFn!: ((optionList: T[], filter: string) => T[]); /** diff --git a/UI/Web/src/app/user-settings/series-bookmarks/series-bookmarks.component.html b/UI/Web/src/app/user-settings/series-bookmarks/series-bookmarks.component.html index 334110032..047b14381 100644 --- a/UI/Web/src/app/user-settings/series-bookmarks/series-bookmarks.component.html +++ b/UI/Web/src/app/user-settings/series-bookmarks/series-bookmarks.component.html @@ -5,7 +5,7 @@
      • - {{series.name | titlecase}} + {{series.name | titlecase}}  {{getBookmarkPages(series.id)}}
        -

        diff --git a/UI/Web/src/assets/themes/dark.scss b/UI/Web/src/assets/themes/dark.scss index 8a5545fa8..7f49264ca 100644 --- a/UI/Web/src/assets/themes/dark.scss +++ b/UI/Web/src/assets/themes/dark.scss @@ -29,6 +29,8 @@ color: $dark-primary-color; } + + .accent { background-color: $dark-form-background !important; @@ -175,6 +177,10 @@ background-color: $dark-card-color; color: $dark-text-color; border-color: $dark-form-border; + + div[role="tabpanel"] { + background-color: rgba(52, 60, 70, 0.5); // This is a good accent color + } } .section-title { diff --git a/UI/Web/src/theme/_colors.scss b/UI/Web/src/theme/_colors.scss index 8500c1cce..31fbdede7 100644 --- a/UI/Web/src/theme/_colors.scss +++ b/UI/Web/src/theme/_colors.scss @@ -16,6 +16,9 @@ $dark-form-readonly: #434648; $dark-item-accent-bg: #292d32; +$white-item-accent-bg: rgba(247, 247, 247, 1); + + //========================= // Ratings //========================= @@ -29,6 +32,7 @@ $rating-empty: #b0c4de; // --drawer-background-color: #FFF; // } + $theme-colors: ( "primary": $primary-color, "danger": $error-color