diff --git a/CHANGELOG.md b/CHANGELOG.md index dad52b7f8..1bbadcf46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.7.3] - 2019-05-15 +## [0.8.0] - 2019-05-20 +### Added +- Chart series +### Fixed +- Targeting when value is present in key +### Improved +- Labels for charts are clearer for user + +## [0.7.3] - 2019-05-13 ### Improved - User impersonation by server admin ### Fixed @@ -95,7 +103,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Advertiser features (Campaigns & Ads) - Publisher features (Sites & AdUnits) -[Unreleased]: https://github.com/adshares/adpanel/compare/v0.7.3...develop +[Unreleased]: https://github.com/adshares/adpanel/compare/v0.8.0...develop +[0.8.0]: https://github.com/adshares/adpanel/compare/v0.7.3...v0.8.0 [0.7.3]: https://github.com/adshares/adpanel/compare/v0.7.2...v0.7.3 [0.7.2]: https://github.com/adshares/adpanel/compare/v0.7.0...v0.7.2 [0.7.0]: https://github.com/adshares/adpanel/compare/v0.6.7...v0.7.0 diff --git a/src/app/advertiser/campaign-details/campaign-details.component.ts b/src/app/advertiser/campaign-details/campaign-details.component.ts index 8dc645f95..14bb6d84a 100644 --- a/src/app/advertiser/campaign-details/campaign-details.component.ts +++ b/src/app/advertiser/campaign-details/campaign-details.component.ts @@ -118,13 +118,13 @@ export class CampaignDetailsComponent extends HandleSubscription implements OnIn chartFilterSettings.currentFrom, chartFilterSettings.currentTo, chartFilterSettings.currentFrequency, - chartFilterSettings.currentSeries, + chartFilterSettings.currentSeries.value, 'campaigns', id, ) .subscribe(data => { this.barChartData[0].data = data.values; - this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries; + this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries.label; this.barChartLabels = data.timestamps.map((item) => moment(item).format()); this.barChartValue = data.total; this.barChartDifference = data.difference; diff --git a/src/app/advertiser/dashboard/dashboard.component.ts b/src/app/advertiser/dashboard/dashboard.component.ts index 948f1fe50..e5752c2a8 100644 --- a/src/app/advertiser/dashboard/dashboard.component.ts +++ b/src/app/advertiser/dashboard/dashboard.component.ts @@ -64,14 +64,13 @@ export class DashboardComponent extends HandleSubscription implements OnInit { chartFilterSettings.currentFrom, chartFilterSettings.currentTo, chartFilterSettings.currentFrequency, - chartFilterSettings.currentSeries, + chartFilterSettings.currentSeries.value, 'campaigns', chartFilterSettings.currentAssetId, ) .subscribe(data => { this.barChartData[0].data = data.values; - this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries; - + this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries.label; this.barChartLabels = data.timestamps.map(item => moment(item).format()); this.barChartValue = data.total; this.barChartDifference = data.difference; diff --git a/src/app/advertiser/edit-campaign/edit-campaign-create-ads/edit-campaign-create-ads.component.ts b/src/app/advertiser/edit-campaign/edit-campaign-create-ads/edit-campaign-create-ads.component.ts index 7dda1a13d..c6fa6ede6 100644 --- a/src/app/advertiser/edit-campaign/edit-campaign-create-ads/edit-campaign-create-ads.component.ts +++ b/src/app/advertiser/edit-campaign/edit-campaign-create-ads/edit-campaign-create-ads.component.ts @@ -176,7 +176,6 @@ export class EditCampaignCreateAdsComponent extends HandleSubscription implement event.target.value = ''; } this.adjustBannerName(form); - if (isUploadedTypeValid && isImageSizeValid) { this.sendImage(file, adIndex, form); } else { @@ -192,6 +191,10 @@ export class EditCampaignCreateAdsComponent extends HandleSubscription implement upload: true }; } + + if (!!event.target) { + event.target.value = ''; // this is necessary when user changes type of the banner and then uploads the same file + } } adjustBannerName(form: FormGroup): void { diff --git a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.html b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.html index 31c1bea3b..31da5addc 100644 --- a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.html +++ b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.html @@ -3,9 +3,8 @@
-
- {{ assetSeries }} + {{ assetSeries.label }}
diff --git a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.scss b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.scss index 188405080..fb00b3b27 100644 --- a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.scss +++ b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.scss @@ -15,4 +15,10 @@ } .user-filters { max-width: 400px; + display: flex; + flex-wrap: nowrap; + + &__select-wrapper { + max-width: 200px; + } } diff --git a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.ts b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.ts index 92d7d9686..2a53a3c7a 100644 --- a/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.ts +++ b/src/app/common/components/chart-filter-by-type/chart-filter-by-type.component.ts @@ -1,14 +1,13 @@ -import {Component, EventEmitter, OnInit, Output, Input} from '@angular/core'; -import {Store} from '@ngrx/store'; +import { Component, EventEmitter, OnInit, Output, Input } from '@angular/core'; +import { Store } from '@ngrx/store'; -import {User} from 'models/user.model'; -import {AppState} from 'models/app-state.model'; -import {adminChartSeriesEnum, advChartSeriesEnum, pubChartSeriesEnum} from 'models/enum/chart.enum'; -import {enumToArray} from 'common/utilities/helpers'; -import {HandleSubscription} from 'common/handle-subscription'; -import {Site} from "models/site.model"; -import {Router} from "@angular/router"; -import {Ad} from "models/campaign.model"; +import { User } from 'models/user.model'; +import { AppState } from 'models/app-state.model'; +import { advChartSeriesEnum, pubChartSeriesEnum } from 'models/enum/chart.enum'; +import { HandleSubscription } from 'common/handle-subscription'; +import { Site } from "models/site.model"; +import { Router } from "@angular/router"; +import { seriesType } from "models/chart/chart-filter-settings.model"; interface AssetInfo { id: number; @@ -22,15 +21,12 @@ interface AssetInfo { }) export class ChartFilterByTypeComponent extends HandleSubscription implements OnInit { @Output() updateId: EventEmitter = new EventEmitter(); - @Output() updateSeries: EventEmitter = new EventEmitter(); + @Output() updateSeries: EventEmitter = new EventEmitter(); @Input() detailsPage: boolean; - userData: User; - currentAssetId = 0; - currentAssetSeries: string = enumToArray(advChartSeriesEnum)[0]; - currentAdminAssetSeries: string = enumToArray(adminChartSeriesEnum)[0]; - chartSeries: string[]; + currentAssetSeries: seriesType; + chartSeries; assetsInfo: AssetInfo[]; constructor(private store: Store, private router: Router) { @@ -39,19 +35,19 @@ export class ChartFilterByTypeComponent extends HandleSubscription implements On ngOnInit() { const userDataSubscription = this.store.select('state', 'user', 'data') + .first() .subscribe(userData => { this.userData = userData; this.userData.isPublisher = !!this.router.url.match('/publisher/'); this.userData.isAdvertiser = !!this.router.url.match('/advertiser/'); this.setInitialDataByUserType(); }); - this.subscriptions.push(userDataSubscription); } setInitialDataByUserType() { if (this.userData.isAdvertiser) { - this.chartSeries = enumToArray(advChartSeriesEnum); + this.setChartSeriesArray(advChartSeriesEnum); const userCampaignsSubscription = this.store.select('state', 'advertiser', 'campaigns') .subscribe((campaigns) => { this.assetsInfo = campaigns.map( @@ -63,7 +59,7 @@ export class ChartFilterByTypeComponent extends HandleSubscription implements On }); this.subscriptions.push(userCampaignsSubscription); } else if (this.userData.isPublisher) { - this.chartSeries = enumToArray(pubChartSeriesEnum); + this.setChartSeriesArray(pubChartSeriesEnum); const userSiteSubscription = this.store.select('state', 'publisher', 'sites') .subscribe((sites: Site[]) => { this.assetsInfo = sites.map( @@ -75,8 +71,18 @@ export class ChartFilterByTypeComponent extends HandleSubscription implements On }); this.subscriptions.push(userSiteSubscription); } else { - this.chartSeries = enumToArray(advChartSeriesEnum); + this.setChartSeriesArray(advChartSeriesEnum); } + this.currentAssetSeries = this.chartSeries[0]; + } + + setChartSeriesArray(seriesEnum) { + this.chartSeries = Object.entries(seriesEnum).map(dataArr => { + return { + label: dataArr[1], + value: dataArr[0], + } + }); } updateAssetId(event) { diff --git a/src/app/common/components/chart/chart-settings/chart-settings.helpers.ts b/src/app/common/components/chart/chart-settings/chart-settings.helpers.ts index 6725c66ae..6f87e6989 100644 --- a/src/app/common/components/chart/chart-settings/chart-settings.helpers.ts +++ b/src/app/common/components/chart/chart-settings/chart-settings.helpers.ts @@ -1,15 +1,16 @@ -import * as moment from "moment"; +import * as moment from 'moment'; import { DAY_AND_MONTH_FORMAT, DAY_AND_TIME_FORMAT, MONTH_AND_YEAR_FORMAT, TIME_FORMAT, - WEEK_AND_MONTH_FORMAT, YEAR_FORMAT -} from "common/utilities/consts"; -import { enumToObject, formatMoney } from "common/utilities/helpers"; -import { advChartSeriesEnum, pubChartSeriesEnum } from "models/enum/chart.enum"; -import { ChartComponent } from "common/components/chart/chart.component"; -import { environment } from "environments/environment"; + WEEK_AND_MONTH_FORMAT, + YEAR_FORMAT, +} from 'common/utilities/consts'; +import { formatMoney } from 'common/utilities/helpers'; +import { advChartSeriesEnum, pubChartSeriesEnum } from 'models/enum/chart.enum'; +import { ChartComponent } from 'common/components/chart/chart.component'; +import { environment } from 'environments/environment'; export const adjustLabelFormat = (value, values) => { const daysSpan = moment(values[values.length - 1]).diff(moment(values[0]), 'days'); @@ -29,18 +30,15 @@ export const adjustLabelFormat = (value, values) => { }; export const adjustTooltipValueFormat = (value: string): string => { - const options = { - ...enumToObject(pubChartSeriesEnum), - ...enumToObject(advChartSeriesEnum) - }; const type = ChartComponent.seriesType; switch (type) { - case options.SUM: - case options.CPC: - case options.CPM: - case options.RPM: - case options.RPC: + case advChartSeriesEnum.sum: + case advChartSeriesEnum.cpc: + case advChartSeriesEnum.cpm: + case pubChartSeriesEnum.sum: + case pubChartSeriesEnum.rpc: + case pubChartSeriesEnum.rpm: const val = parseInt(value); return `${type}: ${val > 0 ? formatMoney(val, 2) : 0} ${environment.currencyCode}`; default: @@ -49,19 +47,17 @@ export const adjustTooltipValueFormat = (value: string): string => { }; export const adjustYAxesTics = (value) => { - const options = { - ...enumToObject(pubChartSeriesEnum), - ...enumToObject(advChartSeriesEnum) - }; + const type = ChartComponent.seriesType; - switch (ChartComponent.seriesType) { - case options.SUM: - case options.CPC: - case options.CPM: - case options.RPM: - case options.RPC: + switch (type) { + case advChartSeriesEnum.sum: + case advChartSeriesEnum.cpc: + case advChartSeriesEnum.cpm: + case pubChartSeriesEnum.sum: + case pubChartSeriesEnum.rpc: + case pubChartSeriesEnum.rpm: const val = parseInt(value); - return `${environment.currencySymbol}${val > 0 ? formatMoney(val,2) : 0}`; + return `${environment.currencySymbol}${val > 0 ? formatMoney(val, 2) : 0}`; default: return `${value}`; } diff --git a/src/app/common/components/chart/chart.component.ts b/src/app/common/components/chart/chart.component.ts index 76bfdf029..5bdacd4b9 100644 --- a/src/app/common/components/chart/chart.component.ts +++ b/src/app/common/components/chart/chart.component.ts @@ -23,6 +23,7 @@ import * as commonActions from 'store/common/common.actions'; import { chartSeriesEnum } from "models/enum/chart.enum"; import { enumToArray } from "common/utilities/helpers"; import { ChartLabels } from "models/chart/chart-labels.model"; +import { chartSeriesInitialState } from "models/initial-state/chart-filter-settings"; @Component({ @@ -39,7 +40,6 @@ export class ChartComponent extends HandleSubscription implements OnInit, OnDest currentChartFilterSettings: ChartFilterSettings; barChartOptions: ChartOptions = chartOptions; barChartColors: ChartColors[] = chartColors; - initialSeries = enumToArray(chartSeriesEnum)[0]; static seriesType; constructor(private store: Store) { @@ -105,7 +105,7 @@ export class ChartComponent extends HandleSubscription implements OnInit, OnDest resetSettings() { const reset = { ...this.currentChartFilterSettings, - currentSeries: this.initialSeries + currentSeries: chartSeriesInitialState }; this.store.dispatch(new commonActions.SetChartFilterSettings(reset)); } diff --git a/src/app/common/components/targeting/targeting.helpers.ts b/src/app/common/components/targeting/targeting.helpers.ts index 9155ea09b..8c7f2ff6e 100644 --- a/src/app/common/components/targeting/targeting.helpers.ts +++ b/src/app/common/components/targeting/targeting.helpers.ts @@ -129,9 +129,13 @@ export function parseTargetingForBackend(chosenTargeting: AssetTargeting) { [chosenTargeting.requires, chosenTargeting.excludes].forEach((targetingList, index) => { targetingList.forEach(targeting => { - const keyPartials = targeting.id.replace(`-${targeting.value}`,'').split('-'); - const parsedTargetingList = index === 0 ? parsedTargeting.requires : parsedTargeting.excludes; - createPathObject(parsedTargetingList, keyPartials, targeting.value); + const suffix = `-${targeting.value}`; + + if (targeting.id.endsWith(suffix)) { + const keyPartials = targeting.id.slice(0, -(suffix.length)).split('-'); + const parsedTargetingList = index === 0 ? parsedTargeting.requires : parsedTargeting.excludes; + createPathObject(parsedTargetingList, keyPartials, targeting.value); + } }); }); diff --git a/src/app/models/chart/chart-filter-settings.model.ts b/src/app/models/chart/chart-filter-settings.model.ts index 590aad55a..e93bbf242 100644 --- a/src/app/models/chart/chart-filter-settings.model.ts +++ b/src/app/models/chart/chart-filter-settings.model.ts @@ -6,10 +6,15 @@ export interface ChartFilterSettings { currentFrequency: string; currentAssetId: number; currentBannerId: number; - currentSeries?: string; + currentSeries?: seriesType; type?: string; } +export interface seriesType { + label: string; + value: string; +} + export interface TimespanFilter { from: string | Moment; to: string | Moment; diff --git a/src/app/models/enum/chart.enum.ts b/src/app/models/enum/chart.enum.ts index bcd0ed344..046034e1b 100644 --- a/src/app/models/enum/chart.enum.ts +++ b/src/app/models/enum/chart.enum.ts @@ -14,20 +14,27 @@ export enum chartSeriesEnum { } export enum pubChartSeriesEnum { - VIEW, - CLICK, - RPC, - CTR, - RPM, - SUM + view = 'Views', + click = 'Clicks', + rpc = 'AVG Revenue / Click', + ctr = 'Click-through Rate', + rpm = 'AVG Revenue / Mile', + sum = 'Revenue', + viewUnique = 'Unique Views', + viewInvalidRate = 'Invalid Views Rate', + clickInvalidRate = 'Invalid Clicks Rate', } + export enum advChartSeriesEnum { - VIEW, - CLICK, - CPC, - CTR, - CPM, - SUM + view = 'Views', + click = 'Clicks', + cpc = 'AVG Cost / Click', + ctr = 'Click-through Rate', + cpm = 'AVG Cost / Mile', + sum = 'Cost', + viewUnique = 'Unique Views', + viewInvalidRate = 'Invalid Views Rate', + clickInvalidRate = 'Invalid Clicks Rate', } export enum filterPresetsEnum { diff --git a/src/app/models/initial-state/chart-filter-settings.ts b/src/app/models/initial-state/chart-filter-settings.ts index 58c39ecf6..f6cb10316 100644 --- a/src/app/models/initial-state/chart-filter-settings.ts +++ b/src/app/models/initial-state/chart-filter-settings.ts @@ -1,11 +1,16 @@ import * as moment from 'moment'; import { ChartFilterSettings } from 'models/chart/chart-filter-settings.model'; +export const chartSeriesInitialState = { + label: 'View', + value: 'view' +}; + export const chartFilterSettingsInitialState: ChartFilterSettings = { currentTo: moment().format(), currentFrom: moment().subtract(30, 'days').format(), currentFrequency: 'day', currentAssetId: 0, currentBannerId: 0, - currentSeries: 'view', + currentSeries: chartSeriesInitialState, }; diff --git a/src/app/publisher/dashboard/dashboard.component.ts b/src/app/publisher/dashboard/dashboard.component.ts index b82771999..2b57ee853 100644 --- a/src/app/publisher/dashboard/dashboard.component.ts +++ b/src/app/publisher/dashboard/dashboard.component.ts @@ -64,14 +64,13 @@ export class DashboardComponent extends HandleSubscription implements OnInit { chartFilterSettings.currentFrom, chartFilterSettings.currentTo, chartFilterSettings.currentFrequency, - chartFilterSettings.currentSeries, + chartFilterSettings.currentSeries.value, 'sites', chartFilterSettings.currentAssetId, ) .subscribe(data => { this.barChartData[0].data = data.values; - this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries; - + this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries.label; this.barChartLabels = data.timestamps.map(item => moment(item).format()); this.barChartValue = data.total; this.barChartDifference = data.difference; diff --git a/src/app/publisher/site-details/site-details.component.ts b/src/app/publisher/site-details/site-details.component.ts index 04bc0da41..ffc7fcf9d 100644 --- a/src/app/publisher/site-details/site-details.component.ts +++ b/src/app/publisher/site-details/site-details.component.ts @@ -137,13 +137,13 @@ export class SiteDetailsComponent extends HandleSubscription implements OnInit { chartFilterSettings.currentFrom, chartFilterSettings.currentTo, chartFilterSettings.currentFrequency, - chartFilterSettings.currentSeries, + chartFilterSettings.currentSeries.value, 'sites', id ) .subscribe(data => { this.barChartData[0].data = data.values; - this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries; + this.barChartData[0].currentSeries = this.currentChartFilterSettings.currentSeries.label; this.barChartLabels = data.timestamps.map((item) => moment(item).format()); this.barChartValue = data.total; this.barChartDifference = data.difference;