feat: add map module

This commit is contained in:
Jovan Krunić
2021-07-13 07:57:09 +00:00
parent d696215d08
commit c1c9a92ec9
44 changed files with 2138 additions and 93 deletions

View File

@@ -36,44 +36,46 @@ import {DataProvider} from './data.provider';
import {DataDetailContentComponent} from './detail/data-detail-content.component';
import {DataDetailComponent} from './detail/data-detail.component';
import {AddressDetailComponent} from './elements/address-detail.component';
import {LongInlineTextComponent} from './elements/long-inline-text.component';
import {OffersDetailComponent} from './elements/offers-detail.component';
import {OffersInListComponent} from './elements/offers-in-list.component';
import {OriginDetailComponent} from './elements/origin-detail.component';
import {OriginInListComponent} from './elements/origin-in-list.component';
import {SimpleCardComponent} from './elements/simple-card.component';
import {SkeletonListItemComponent} from './elements/skeleton-list-item.component';
import {SkeletonSegmentComponent} from './elements/skeleton-segment-button.component';
import {SkeletonSimpleCardComponent} from './elements/skeleton-simple-card.component';
import {DataListItemComponent} from './list/data-list-item.component';
import {DataListComponent} from './list/data-list.component';
import {FoodDataListComponent} from './list/food-data-list.component';
import {SearchPageComponent} from './list/search-page.component';
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';
import {ArticleDetailContentComponent} from './types/article/article-detail-content.component';
import {ArticleListItemComponent} from './types/article/article-list-item.component';
import {CatalogDetailContentComponent} from './types/catalog/catalog-detail-content.component';
import {CatalogListItemComponent} from './types/catalog/catalog-list-item.component';
import {DateSeriesDetailContentComponent} from './types/date-series/date-series-detail-content.component';
import {DateSeriesListItemComponent} from './types/date-series/date-series-list-item.component';
import {DishDetailContentComponent} from './types/dish/dish-detail-content.component';
import {DishListItemComponent} from './types/dish/dish-list-item.component';
import {EventDetailContentComponent} from './types/event/event-detail-content.component';
import {EventListItemComponent} from './types/event/event-list-item.component';
import {FavoriteDetailContentComponent} from './types/favorite/favorite-detail-content.component';
import {FavoriteListItemComponent} from './types/favorite/favorite-list-item.component';
import {MessageDetailContentComponent} from './types/message/message-detail-content.component';
import {MessageListItemComponent} from './types/message/message-list-item.component';
import {OrganizationDetailContentComponent} from './types/organization/organization-detail-content.component';
import {OrganizationListItemComponent} from './types/organization/organization-list-item.component';
import {PersonDetailContentComponent} from './types/person/person-detail-content.component';
import {PersonListItemComponent} from './types/person/person-list-item.component';
import {PlaceDetailContentComponent} from './types/place/place-detail-content.component';
import {PlaceListItemComponent} from './types/place/place-list-item.component';
import {PlaceMensaDetailComponent} from './types/place/special/mensa/place-mensa-detail.component';
import {SemesterDetailContentComponent} from './types/semester/semester-detail-content.component';
import {SemesterListItemComponent} from './types/semester/semester-list-item.component';
import {VideoDetailContentComponent} from './types/video/video-detail-content.component';
import {MapWidgetComponent} from '../map/widget/map-widget.component';
import {LeafletModule} from '@asymmetrik/ngx-leaflet';
import {ArticleListItemComponent} from './types/article/article-list-item.component';
import {SkeletonSimpleCardComponent} from './elements/skeleton-simple-card.component';
import {CatalogListItemComponent} from './types/catalog/catalog-list-item.component';
import {DataListItemComponent} from './list/data-list-item.component';
import {DateSeriesListItemComponent} from './types/date-series/date-series-list-item.component';
import {DishListItemComponent} from './types/dish/dish-list-item.component';
import {FavoriteListItemComponent} from './types/favorite/favorite-list-item.component';
import {LongInlineTextComponent} from './elements/long-inline-text.component';
import {MessageListItemComponent} from './types/message/message-list-item.component';
import {OrganizationListItemComponent} from './types/organization/organization-list-item.component';
import {PersonListItemComponent} from './types/person/person-list-item.component';
import {SemesterListItemComponent} from './types/semester/semester-list-item.component';
import {SkeletonListItemComponent} from './elements/skeleton-list-item.component';
import {SkeletonSegmentComponent} from './elements/skeleton-segment-button.component';
import {VideoListItemComponent} from './types/video/video-list-item.component';
/**
@@ -81,17 +83,19 @@ import {VideoListItemComponent} from './types/video/video-list-item.component';
*/
@NgModule({
declarations: [
ActionChipListComponent,
AddEventActionChipComponent,
AddEventPopoverComponent,
OffersDetailComponent,
OffersInListComponent,
AddressDetailComponent,
ArticleDetailContentComponent,
ArticleListItemComponent,
SimpleCardComponent,
SkeletonSimpleCardComponent,
CatalogDetailContentComponent,
CatalogListItemComponent,
DataDetailComponent,
DataDetailContentComponent,
DataIconPipe,
FoodDataListComponent,
DataListComponent,
DataListItemComponent,
DateSeriesDetailContentComponent,
@@ -102,13 +106,10 @@ import {VideoListItemComponent} from './types/video/video-list-item.component';
EventListItemComponent,
FavoriteDetailContentComponent,
FavoriteListItemComponent,
FoodDataListComponent,
LocateActionChipComponent,
LongInlineTextComponent,
MapWidgetComponent,
MessageDetailContentComponent,
MessageListItemComponent,
OffersDetailComponent,
OffersInListComponent,
OrganizationDetailContentComponent,
OrganizationListItemComponent,
OriginDetailComponent,
@@ -121,20 +122,22 @@ import {VideoListItemComponent} from './types/video/video-list-item.component';
SearchPageComponent,
SemesterDetailContentComponent,
SemesterListItemComponent,
SimpleCardComponent,
SkeletonListItemComponent,
SkeletonSegmentComponent,
SkeletonSimpleCardComponent,
VideoDetailContentComponent,
VideoListItemComponent,
DataIconPipe,
ActionChipListComponent,
AddEventActionChipComponent,
LocateActionChipComponent,
],
entryComponents: [DataListComponent],
imports: [
CommonModule,
DataRoutingModule,
FormsModule,
HttpClientModule,
IonicModule.forRoot(),
CommonModule,
FormsModule,
DataRoutingModule,
HttpClientModule,
LeafletModule,
MarkdownModule.forRoot(),
MenuModule,
MomentModule.forRoot({
@@ -148,5 +151,15 @@ import {VideoListItemComponent} from './types/video/video-list-item.component';
ThingTranslateModule.forChild(),
],
providers: [DataProvider, DataFacetsProvider, Network, StAppsWebHttpClient],
exports: [
DataListComponent,
DataListItemComponent,
DataDetailComponent,
SkeletonSimpleCardComponent,
SkeletonListItemComponent,
DataIconPipe,
PlaceListItemComponent,
DataDetailContentComponent,
],
})
export class DataModule {}

View File

@@ -1,3 +1,18 @@
<ion-item class="ion-text-wrap" lines="inset">
<ion-thumbnail slot="start" class="ion-margin-end">
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
</ion-thumbnail>
<ion-grid>
<ion-row>
<ion-col>
<div class="ion-text-wrap">
<h2 class="name">{{ item.name }}</h2>
<ion-note>{{ item.type }}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<stapps-simple-card
*ngIf="item.description"
[title]="'Description'"

View File

@@ -38,24 +38,6 @@
<stapps-skeleton-simple-card></stapps-skeleton-simple-card>
</ng-container>
<ng-container *ngSwitchDefault>
<ion-item class="ion-text-wrap" lines="inset">
<ion-thumbnail slot="start" class="ion-margin-end">
<ion-icon
color="medium"
[attr.name]="item.type | dataIcon"
></ion-icon>
</ion-thumbnail>
<ion-grid *ngSwitchDefault>
<ion-row>
<ion-col>
<div class="ion-text-wrap">
<h2 class="name">{{ item.name }}</h2>
<ion-note>{{ item.type }}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<stapps-data-detail-content [item]="item"></stapps-data-detail-content>
</ng-container>
</div>

View File

@@ -15,4 +15,18 @@
padding-top: 0;
padding-bottom: 0;
}
ion-note {
ul {
margin: 0;
padding: 0;
li {
list-style-type: none;
display: inline;
}
li:not(:first-child):before {
content: "";
}
}
}
}

View File

@@ -2,15 +2,23 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {DataListComponent} from './data-list.component';
import {TranslateModule} from '@ngx-translate/core';
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {ConfigProvider} from '../../config/config.provider';
describe('DataListComponent', () => {
let component: DataListComponent;
let fixture: ComponentFixture<DataListComponent>;
let configProviderMock: jasmine.SpyObj<ConfigProvider>;
beforeEach(async(() => {
configProviderMock = jasmine.createSpyObj('ConfigProvider', {
getValue: () => Promise.resolve({lat: 123, lng: 123}),
});
TestBed.configureTestingModule({
declarations: [DataListComponent],
imports: [TranslateModule.forRoot()],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [{provide: ConfigProvider, useValue: configProviderMock}],
}).compileComponents();
}));

View File

@@ -1,4 +1,4 @@
<stapps-context></stapps-context>
<stapps-context contentId="data-list"></stapps-context>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
@@ -13,7 +13,9 @@
<ion-searchbar
(ngModelChange)="searchStringChanged($event)"
[(ngModel)]="queryText"
></ion-searchbar>
showClearButton="always"
>
</ion-searchbar>
</ion-toolbar>
</ion-header>

View File

@@ -27,6 +27,7 @@ import {DataProvider} from '../../data.provider';
*/
@Component({
providers: [DataProvider],
styleUrls: ['place-detail-content.scss'],
selector: 'stapps-place-detail-content',
templateUrl: 'place-detail-content.html',
})
@@ -41,7 +42,9 @@ export class PlaceDetailContentComponent {
*
* @param item TODO
*/
// tslint:disable-next-line:completed-docs prefer-function-over-method
hasCategories(item: SCThings): item is SCThings & {categories: string[]} {
// tslint:disable-next-line:completed-docs
return typeof (item as {categories: string[]}).categories !== 'undefined';
}

View File

@@ -1,6 +1,5 @@
<stapps-place-mensa-detail-content
[item]="item"
[language]="language"
*ngIf="isMensaThing(item)"
></stapps-place-mensa-detail-content>
<ng-container *ngIf="item.type !== 'floor'">
@@ -26,8 +25,9 @@
}}</a>
</ion-card-content>
</ion-card>
<stapps-address-detail
*ngIf="item.inPlace && item.inPlace.address"
[address]="item.inPlace.address"
></stapps-address-detail>
</ng-container>
<ng-container *ngIf="item.type !== 'floor'">
<ion-card *ngIf="item.geo" class="map-widget">
<stapps-map-widget [place]="item" expandable="true"></stapps-map-widget>
</ion-card>
</ng-container>

View File

@@ -0,0 +1,4 @@
ion-card.map-widget {
height: 300px;
width: auto;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 StApps
* Copyright (C) 2019-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.
@@ -14,18 +14,55 @@
*/
import {Component, Input} from '@angular/core';
import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom} from '@openstapps/core';
import {DataListItemComponent} from '../../list/data-list-item.component';
import {PositionService} from '../../../map/position.service';
type placeTypes = (SCBuilding | SCRoom | SCPointOfInterest | SCFloor) & {
distance?: number;
};
/**
* TODO
* Provide information if a place is a floor
*
* @param place A place to check
*/
function isSCFloor(place: placeTypes): place is SCFloor {
return place.type === 'floor';
}
/**
* Shows a place as a list item
*/
@Component({
selector: 'stapps-place-list-item',
templateUrl: 'place-list-item.html',
})
export class PlaceListItemComponent extends DataListItemComponent {
export class PlaceListItemComponent {
/**
* TODO
* Item getter
*/
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
get item(): placeTypes {
return this._item;
}
/**
* An item to show (setter is used as there were issues assigning the distance to the right place in a list)
*/
@Input() set item(item: placeTypes) {
this._item = item;
if (!isSCFloor(item)) {
this.distance = this.positionService.getDistance(item.geo.point);
}
}
/**
* An item to show
*/
private _item: placeTypes;
/**
* Distance in meters
*/
distance?: number;
constructor(private positionService: PositionService) {}
}

View File

@@ -6,7 +6,15 @@
<p *ngIf="item.description">
{{ 'description' | thingTranslate: item }}
</p>
<ion-note>{{ 'type' | thingTranslate: item }} </ion-note>
<ion-note>
<ul>
<li>{{ 'type' | thingTranslate: item }}</li>
<li *ngIf="distance">
<ion-icon name="walk"></ion-icon
>{{ distance | numberLocalized: '1.0-0' }} m
</li>
</ul>
</ion-note>
</div>
</ion-col>
<ion-col width-20 text-right *ngIf="item.type !== 'building'">