diff --git a/src/app/modules/data/chips/filter/chip-filter.component.html b/src/app/modules/data/chips/filter/chip-filter.component.html
new file mode 100644
index 00000000..e76027f7
--- /dev/null
+++ b/src/app/modules/data/chips/filter/chip-filter.component.html
@@ -0,0 +1,7 @@
+
+
+ {{ displayValue }}
+
diff --git a/src/app/modules/data/chips/filter/chip-filter.component.scss b/src/app/modules/data/chips/filter/chip-filter.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/modules/data/chips/filter/chip-filter.component.ts b/src/app/modules/data/chips/filter/chip-filter.component.ts
new file mode 100644
index 00000000..5c8a258f
--- /dev/null
+++ b/src/app/modules/data/chips/filter/chip-filter.component.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+import {Component, EventEmitter, Input, Output} from '@angular/core';
+/**
+ * Shows a chip filter
+ */
+@Component({
+ selector: 'stapps-chip-filter',
+ templateUrl: './chip-filter.component.html',
+ styleUrls: ['./chip-filter.component.scss'],
+})
+export class ChipFilterComponent {
+ /**
+ * If the chip (filter) is active
+ */
+ @Input() active: boolean;
+
+ /**
+ * Text to display on the chip
+ */
+ @Input() displayValue: string;
+
+ /**
+ * Emits when the chip has been activated/deactivated
+ */
+ @Output() toggle = new EventEmitter();
+
+ /**
+ * Value to emit when chip has been activated/deactivated
+ */
+ @Input() value: unknown;
+
+ /**
+ * Signalize that the chip filter has been activated/deactivated
+ */
+ emitToggle(value: unknown) {
+ this.toggle.emit(value);
+ }
+}
diff --git a/src/app/modules/data/data.provider.ts b/src/app/modules/data/data.provider.ts
index 96aa5c65..4c5b8c1d 100644
--- a/src/app/modules/data/data.provider.ts
+++ b/src/app/modules/data/data.provider.ts
@@ -19,8 +19,10 @@ import {
SCMultiSearchResponse,
SCSearchRequest,
SCSearchResponse,
+ SCSearchValueFilter,
SCThingOriginType,
SCThings,
+ SCThingsField,
SCThingType,
} from '@openstapps/core';
import {SCSaveableThing} from '@openstapps/core';
@@ -88,6 +90,25 @@ export class DataProvider {
*/
storageProvider: StorageProvider;
+ /**
+ * Simplify creation of a value filter
+ *
+ * @param field Database field for apply the filter to
+ * @param value Value to match with
+ */
+ static createValueFilter(
+ field: SCThingsField,
+ value: string,
+ ): SCSearchValueFilter {
+ return {
+ type: 'value',
+ arguments: {
+ field: field,
+ value: value,
+ },
+ };
+ }
+
/**
* TODO
*
diff --git a/src/app/modules/data/detail/data-detail-content.component.ts b/src/app/modules/data/detail/data-detail-content.component.ts
index 6dc7d06f..7cd96354 100644
--- a/src/app/modules/data/detail/data-detail-content.component.ts
+++ b/src/app/modules/data/detail/data-detail-content.component.ts
@@ -20,6 +20,7 @@ import {SCThings} from '@openstapps/core';
*/
@Component({
selector: 'stapps-data-detail-content',
+ styleUrls: ['data-detail-content.scss'],
templateUrl: 'data-detail-content.html',
})
export class DataDetailContentComponent {
diff --git a/src/app/modules/data/detail/data-detail-content.html b/src/app/modules/data/detail/data-detail-content.html
index f0e4f9b9..81e3a896 100644
--- a/src/app/modules/data/detail/data-detail-content.html
+++ b/src/app/modules/data/detail/data-detail-content.html
@@ -6,8 +6,8 @@
-
{{ item.name }}
- {{ item.type }}
+
{{ 'name' | thingTranslate: item }}
+ {{ 'type' | thingTranslate: item }}
diff --git a/src/app/modules/data/detail/data-detail-content.scss b/src/app/modules/data/detail/data-detail-content.scss
new file mode 100644
index 00000000..64dd7289
--- /dev/null
+++ b/src/app/modules/data/detail/data-detail-content.scss
@@ -0,0 +1,18 @@
+:host ::ng-deep {
+ ion-slides.work-locations {
+ ion-slide {
+ display: block;
+ text-align: left;
+ }
+ }
+ ion-card {
+ ion-card-header {
+ font-weight: bold;
+ }
+ ion-grid, ion-col {
+ padding-inline-start: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+ }
+}
diff --git a/src/app/modules/data/detail/data-detail.scss b/src/app/modules/data/detail/data-detail.scss
index 8be59279..b862d204 100644
--- a/src/app/modules/data/detail/data-detail.scss
+++ b/src/app/modules/data/detail/data-detail.scss
@@ -12,11 +12,3 @@
}
}
}
-
-::ng-deep {
- ion-grid, ion-col {
- padding-inline-start: 0;
- padding-top: 0;
- padding-bottom: 0;
- }
-}
diff --git a/src/app/modules/data/elements/skeleton-list-item.scss b/src/app/modules/data/elements/skeleton-list-item.scss
index 6d7dd065..e69de29b 100644
--- a/src/app/modules/data/elements/skeleton-list-item.scss
+++ b/src/app/modules/data/elements/skeleton-list-item.scss
@@ -1,7 +0,0 @@
-::ng-deep {
- ion-grid, ion-col {
- padding-inline-start: 0;
- padding-top: 0;
- padding-bottom: 0;
- }
-}
diff --git a/src/app/modules/data/list/data-list-item.scss b/src/app/modules/data/list/data-list-item.scss
index 61c0234b..a0be2a73 100644
--- a/src/app/modules/data/list/data-list-item.scss
+++ b/src/app/modules/data/list/data-list-item.scss
@@ -1,4 +1,4 @@
-.item {
+:host ::ng-deep {
ion-label {
width: 100%;
@@ -7,25 +7,20 @@
flex-direction: column;
}
}
-}
+ ::ng-deep {
+ ion-note {
+ ul {
+ margin: 0;
+ padding: 0;
-::ng-deep {
- ion-grid, ion-col {
- padding-inline-start: 0 ;
- padding-top: 0;
- padding-bottom: 0;
- }
+ li {
+ list-style-type: none;
+ display: inline;
+ }
- ion-note {
- ul {
- margin: 0;
- padding: 0;
- li {
- list-style-type: none;
- display: inline;
- }
- li:not(:first-child):before {
- content: " • ";
+ li:not(:first-child):before {
+ content: " • ";
+ }
}
}
}
diff --git a/src/app/modules/map/item/map-item.component.html b/src/app/modules/map/item/map-item.component.html
index 9311e93b..e970c2a0 100644
--- a/src/app/modules/map/item/map-item.component.html
+++ b/src/app/modules/map/item/map-item.component.html
@@ -1,4 +1,4 @@
-
+
+
+
+
diff --git a/src/app/modules/news/elements/news-filter-settings/news-settings-filter.component.scss b/src/app/modules/news/elements/news-filter-settings/news-settings-filter.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/modules/news/elements/news-filter-settings/news-settings-filter.component.ts b/src/app/modules/news/elements/news-filter-settings/news-settings-filter.component.ts
new file mode 100644
index 00000000..8266a355
--- /dev/null
+++ b/src/app/modules/news/elements/news-filter-settings/news-settings-filter.component.ts
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {
+ newsFilterSettingsFieldsMapping,
+ NewsFilterSettingsNames,
+} from '../../news-filter-settings';
+import {SCSearchValueFilter, SCSetting} from '@openstapps/core';
+import {DataProvider} from '../../../data/data.provider';
+
+@Component({
+ selector: 'stapps-news-settings-filter',
+ templateUrl: './news-settings-filter.component.html',
+ styleUrls: ['./news-settings-filter.component.scss'],
+})
+export class NewsSettingsFilterComponent implements OnInit {
+ /**
+ * A map of the filters where the keys are settings names
+ */
+ filtersMap = new Map();
+
+ /**
+ * Emits the current filters
+ */
+ @Output() filtersChanged = new EventEmitter();
+
+ /**
+ * Provided settings to show the filters for
+ */
+ @Input() settings: SCSetting[];
+
+ ngOnInit() {
+ for (const setting of this.settings) {
+ this.filtersMap.set(
+ setting.name as NewsFilterSettingsNames,
+ DataProvider.createValueFilter(
+ newsFilterSettingsFieldsMapping[
+ setting.name as NewsFilterSettingsNames
+ ],
+ setting.value as string,
+ ),
+ );
+ }
+
+ this.filtersChanged.emit([...this.filtersMap.values()]);
+ }
+
+ /**
+ * To be executed when a chip filter has been enabled/disabled
+ *
+ * @param setting The value of the filter
+ */
+ stateChanged(setting: SCSetting) {
+ if (
+ typeof this.filtersMap.get(setting.name as NewsFilterSettingsNames) !==
+ 'undefined'
+ ) {
+ this.filtersMap.delete(setting.name as NewsFilterSettingsNames);
+ } else {
+ this.filtersMap.set(
+ setting.name as NewsFilterSettingsNames,
+ DataProvider.createValueFilter(
+ newsFilterSettingsFieldsMapping[
+ setting.name as NewsFilterSettingsNames
+ ],
+ setting.value as string,
+ ),
+ );
+ }
+
+ this.filtersChanged.emit([...this.filtersMap.values()]);
+ }
+}
diff --git a/src/app/modules/news/page/news-item.component.ts b/src/app/modules/news/item/news-item.component.ts
similarity index 100%
rename from src/app/modules/news/page/news-item.component.ts
rename to src/app/modules/news/item/news-item.component.ts
diff --git a/src/app/modules/news/page/news-item.html b/src/app/modules/news/item/news-item.html
similarity index 100%
rename from src/app/modules/news/page/news-item.html
rename to src/app/modules/news/item/news-item.html
diff --git a/src/app/modules/news/page/news-item.scss b/src/app/modules/news/item/news-item.scss
similarity index 100%
rename from src/app/modules/news/page/news-item.scss
rename to src/app/modules/news/item/news-item.scss
diff --git a/src/app/modules/news/page/skeleton-news-item.component.ts b/src/app/modules/news/item/skeleton-news-item.component.ts
similarity index 100%
rename from src/app/modules/news/page/skeleton-news-item.component.ts
rename to src/app/modules/news/item/skeleton-news-item.component.ts
diff --git a/src/app/modules/news/page/skeleton-news-item.html b/src/app/modules/news/item/skeleton-news-item.html
similarity index 100%
rename from src/app/modules/news/page/skeleton-news-item.html
rename to src/app/modules/news/item/skeleton-news-item.html
diff --git a/src/app/modules/news/news-filter-settings.ts b/src/app/modules/news/news-filter-settings.ts
new file mode 100644
index 00000000..8860344b
--- /dev/null
+++ b/src/app/modules/news/news-filter-settings.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+import {SCSettingCategories, SCThingsField} from '@openstapps/core';
+/**
+ * Category of settings to use for news filter
+ */
+export const newsFilterSettingsCategory: SCSettingCategories = 'profile';
+/**
+ * Settings to use for news filter
+ */
+export type NewsFilterSettingsNames = 'language' | 'group';
+/**
+ * The mapping between settings and corresponding data fields for building a value filter
+ */
+export const newsFilterSettingsFieldsMapping: {
+ [key in NewsFilterSettingsNames]: SCThingsField;
+} = {
+ language: 'inLanguage',
+ group: 'audiences',
+};
diff --git a/src/app/modules/news/news.module.ts b/src/app/modules/news/news.module.ts
index ecfed80f..d32be81b 100644
--- a/src/app/modules/news/news.module.ts
+++ b/src/app/modules/news/news.module.ts
@@ -18,11 +18,15 @@ import {RouterModule, Routes} from '@angular/router';
import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core';
import {MomentModule} from 'ngx-moment';
+import {ThingTranslateModule} from '../../translation/thing-translate.module';
import {DataModule} from '../data/data.module';
import {SettingsProvider} from '../settings/settings.provider';
-import {NewsItemComponent} from './page/news-item.component';
+import {NewsItemComponent} from './item/news-item.component';
import {NewsPageComponent} from './page/news-page.component';
-import {SkeletonNewsItemComponent} from './page/skeleton-news-item.component';
+import {SkeletonNewsItemComponent} from './item/skeleton-news-item.component';
+import {ChipFilterComponent} from '../data/chips/filter/chip-filter.component';
+import {SettingsModule} from '../settings/settings.module';
+import {NewsSettingsFilterComponent} from './elements/news-filter-settings/news-settings-filter.component';
const newsRoutes: Routes = [{path: 'news', component: NewsPageComponent}];
@@ -31,17 +35,21 @@ const newsRoutes: Routes = [{path: 'news', component: NewsPageComponent}];
*/
@NgModule({
declarations: [
- NewsItemComponent,
NewsPageComponent,
SkeletonNewsItemComponent,
+ NewsItemComponent,
+ ChipFilterComponent,
+ NewsSettingsFilterComponent,
],
imports: [
- CommonModule,
- DataModule,
IonicModule.forRoot(),
- MomentModule,
- RouterModule.forChild(newsRoutes),
TranslateModule.forChild(),
+ RouterModule.forChild(newsRoutes),
+ CommonModule,
+ MomentModule,
+ DataModule,
+ ThingTranslateModule,
+ SettingsModule,
],
providers: [SettingsProvider],
})
diff --git a/src/app/modules/news/news.provider.ts b/src/app/modules/news/news.provider.ts
index 19e09bd1..37a9cb38 100644
--- a/src/app/modules/news/news.provider.ts
+++ b/src/app/modules/news/news.provider.ts
@@ -13,7 +13,13 @@
* this program. If not, see .
*/
import {Injectable} from '@angular/core';
-import {SCMessage} from '@openstapps/core';
+import {
+ SCBooleanFilterArguments,
+ SCMessage,
+ SCSearchBooleanFilter,
+ SCSearchFilter,
+ SCSearchQuery,
+} from '@openstapps/core';
import {DataProvider} from '../data/data.provider';
/**
* Service for providing news messages
@@ -22,34 +28,59 @@ import {DataProvider} from '../data/data.provider';
providedIn: 'root',
})
export class NewsProvider {
- constructor(private dataProvider: DataProvider) {
- }
+ constructor(private dataProvider: DataProvider) {}
/**
* Get news messages
*
* @param size How many messages/news to fetch
* @param from From which (results) page to start
+ * @param filters Additional filters to apply
*/
- async getList(size: number, from: number): Promise {
- const result = await this.dataProvider.search({
+ async getList(
+ size: number,
+ from: number,
+ filters?: SCSearchFilter[],
+ ): Promise {
+ const query: SCSearchQuery = {
filter: {
- type: 'value',
+ type: 'boolean',
arguments: {
- field: 'type',
- value: 'message',
+ filters: [
+ {
+ type: 'value',
+ arguments: {
+ field: 'type',
+ value: 'message',
+ },
+ },
+ ],
+ operation: 'and',
},
},
- sort: [{
- type: 'generic',
- arguments: {
- field: 'datePublished',
+ sort: [
+ {
+ type: 'generic',
+ arguments: {
+ field: 'datePublished',
+ },
+ order: 'desc',
},
- order: 'desc',
- }],
+ ],
size: size,
from: from,
- });
+ };
+
+ if (typeof filters !== 'undefined') {
+ for (const filter of filters) {
+ (
+ (query.filter as SCSearchBooleanFilter)
+ .arguments as SCBooleanFilterArguments
+ ).filters.push(filter);
+ }
+ }
+
+ const result = await this.dataProvider.search(query);
return result.data as SCMessage[];
}
diff --git a/src/app/modules/news/page/news-page.component.ts b/src/app/modules/news/page/news-page.component.ts
index 59e2609f..f3c6b022 100644
--- a/src/app/modules/news/page/news-page.component.ts
+++ b/src/app/modules/news/page/news-page.component.ts
@@ -12,9 +12,20 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*/
-import {Component} from '@angular/core';
+import {Component, OnInit} from '@angular/core';
import {IonRefresher} from '@ionic/angular';
-import {SCMessage} from '@openstapps/core';
+import {
+ SCMessage,
+ SCSearchFilter,
+ SCSearchValueFilter,
+ SCSetting,
+} from '@openstapps/core';
+import {SettingsProvider} from '../../settings/settings.provider';
+import {
+ newsFilterSettingsCategory,
+ newsFilterSettingsFieldsMapping,
+ NewsFilterSettingsNames,
+} from '../news-filter-settings';
import {NewsProvider} from '../news.provider';
/**
* News page component
@@ -23,46 +34,86 @@ import {NewsProvider} from '../news.provider';
selector: 'stapps-news-page',
templateUrl: 'news-page.html',
})
-export class NewsPageComponent {
+export class NewsPageComponent implements OnInit {
/**
* Thing counter to start query the next page from
*/
from = 0;
- /**
- * Page size of queries
- */
- pageSize = 10;
+
/**
* News (messages) to show
*/
news: SCMessage[] = [];
- constructor(private newsProvider: NewsProvider) {}
+ /**
+ * Page size of queries
+ */
+ pageSize = 10;
+
+ /**
+ * Relevant settings
+ */
+ settings: SCSetting[];
+
+ /**
+ * Active filters
+ */
+ filters: SCSearchFilter[];
+
+ constructor(
+ private newsProvider: NewsProvider,
+ private settingsProvider: SettingsProvider,
+ ) {}
/**
* Fetch news from the backend
*/
async fetchNews() {
- this.news = await this.newsProvider.getList(this.pageSize, this.from);
+ this.from = 0;
+ this.news = await this.newsProvider.getList(this.pageSize, this.from, [
+ ...this.filters,
+ ]);
}
/**
* Loads more news
*
- * @param event Signal from the infinite scroll to load more data
+ * @param infiniteScrollElement Infinite scroll element
*/
- // tslint:disable-next-line:no-any
- async loadMore(event: any): Promise {
+ async loadMore(
+ infiniteScrollElement: HTMLIonInfiniteScrollElement,
+ ): Promise {
this.from += this.pageSize;
- this.news = this.news.concat(await this.newsProvider.getList(this.pageSize, this.from));
- event.target.complete();
+ this.news = [
+ ...this.news,
+ ...(await this.newsProvider.getList(this.pageSize, this.from, [
+ ...this.filters,
+ ])),
+ ];
+ await infiniteScrollElement.complete();
}
/**
* Initialize the local variables on component initialization
*/
- ngOnInit() {
- void this.fetchNews();
+ async ngOnInit() {
+ // Helper method to provide the relevant settings
+ const getNewsSettings = async (settingNames: NewsFilterSettingsNames[]) => {
+ const settings = [];
+ for (const settingName of settingNames) {
+ settings.push(
+ await this.settingsProvider.getSetting(
+ newsFilterSettingsCategory,
+ settingName,
+ ),
+ );
+ }
+ return settings;
+ };
+
+ this.settings = await getNewsSettings(
+ Object.keys(newsFilterSettingsFieldsMapping) as NewsFilterSettingsNames[],
+ );
}
/**
@@ -72,12 +123,21 @@ export class NewsPageComponent {
*/
async refresh(refresher: IonRefresher) {
try {
- this.from = 0;
await this.fetchNews();
- } catch (e) {
+ } catch {
this.news = [];
} finally {
await refresher.complete();
}
}
+
+ /**
+ * Executed when filters have been changed
+ *
+ * @param filters Current filters to be used
+ */
+ toggleFilter(filters: SCSearchValueFilter[]) {
+ this.filters = filters;
+ void this.fetchNews();
+ }
}
diff --git a/src/app/modules/news/page/news-page.html b/src/app/modules/news/page/news-page.html
index 86eaadf8..38f1e7df 100644
--- a/src/app/modules/news/page/news-page.html
+++ b/src/app/modules/news/page/news-page.html
@@ -4,19 +4,31 @@
- {{'news.title' | translate}}
+ {{ 'news.title' | translate }}
-
+
-
+
+
+
+
+
+
@@ -27,7 +39,14 @@
-
+
+ {{ 'search.nothing_found' | translate | titlecase }}
+
+
diff --git a/src/app/modules/settings/setting-translate.pipe.ts b/src/app/modules/settings/setting-translate.pipe.ts
new file mode 100644
index 00000000..81db28b2
--- /dev/null
+++ b/src/app/modules/settings/setting-translate.pipe.ts
@@ -0,0 +1,35 @@
+import {Pipe, PipeTransform} from '@angular/core';
+import {TranslateService} from '@ngx-translate/core';
+import {SCSetting} from '@openstapps/core';
+import {ThingTranslatePipe} from '../../translation/thing-translate.pipe';
+import {ThingTranslateService} from '../../translation/thing-translate.service';
+
+/**
+ * Translates a setting value (into the display value in current language)
+ */
+@Pipe({
+ name: 'settingValueTranslate',
+})
+export class SettingTranslatePipe implements PipeTransform {
+ constructor(
+ private readonly translate: TranslateService,
+ private readonly thingTranslate: ThingTranslateService,
+ ) {}
+
+ transform(setting: SCSetting) {
+ const thingTranslatePipe = new ThingTranslatePipe(
+ this.translate,
+ this.thingTranslate,
+ );
+ const translatedSettingValues = thingTranslatePipe.transform(
+ 'values',
+ setting,
+ );
+
+ return translatedSettingValues
+ ? translatedSettingValues[
+ setting.values?.indexOf(setting.value as string) as number
+ ]
+ : undefined;
+ }
+}
diff --git a/src/app/modules/settings/settings.module.ts b/src/app/modules/settings/settings.module.ts
index 3f955911..18ef85b7 100644
--- a/src/app/modules/settings/settings.module.ts
+++ b/src/app/modules/settings/settings.module.ts
@@ -23,6 +23,7 @@ import {ThingTranslateModule} from '../../translation/thing-translate.module';
import {ConfigProvider} from '../config/config.provider';
import {SettingsItemComponent} from './item/settings-item.component';
import {SettingsPageComponent} from './page/settings-page.component';
+import {SettingTranslatePipe} from './setting-translate.pipe';
import {SettingsProvider} from './settings.provider';
const settingsRoutes: Routes = [
@@ -33,15 +34,19 @@ const settingsRoutes: Routes = [
* Settings Module
*/
@NgModule({
- declarations: [SettingsPageComponent, SettingsItemComponent],
- exports: [SettingsItemComponent],
+ declarations: [
+ SettingsPageComponent,
+ SettingsItemComponent,
+ SettingTranslatePipe,
+ ],
+ exports: [SettingsItemComponent, SettingTranslatePipe],
imports: [
CommonModule,
FormsModule,
IonicModule.forRoot(),
- RouterModule.forChild(settingsRoutes),
- ThingTranslateModule.forChild(),
TranslateModule.forChild(),
+ ThingTranslateModule.forChild(),
+ RouterModule.forChild(settingsRoutes),
],
providers: [ConfigProvider, SettingsProvider],
})
diff --git a/src/global.scss b/src/global.scss
index 7421879a..e35371f7 100644
--- a/src/global.scss
+++ b/src/global.scss
@@ -32,6 +32,14 @@ ion-item {
}
}
+ion-item, ion-card.compact {
+ ion-grid, ion-col {
+ padding-inline-start: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+}
+
.notFoundContainer {
display: flex;
flex-direction: column;