Vuetify SoundExchange report.
This commit is contained in:
parent
5b114a5f31
commit
408d4c6a4b
|
@ -1,75 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'method' => 'post',
|
||||
|
||||
'elements' => [
|
||||
|
||||
'report_details' => [
|
||||
'markup',
|
||||
[
|
||||
'label' => _('Important Notes'),
|
||||
'markup' => '
|
||||
<p>This report is intended for licensing in the United States only, for webcasters paying royalties via
|
||||
SoundExchange. Learn more about the requirements for reporting and classification on the
|
||||
<a href="https://www.soundexchange.com/service-provider/reporting-requirements/" target="_blank">
|
||||
SoundExchange web site
|
||||
</a>.</p>
|
||||
<ul>
|
||||
<li>AzuraCast assumes that your station fits SoundExchange Transmission Category A, "Eligible nonsubscription
|
||||
transmissions other than broadcast simulcasts and transmissions of non-music programming." If your
|
||||
station does not fall within this category, update the transmission category field accordingly.
|
||||
<li>The data collected by AzuraCast meets the SoundExchange standard for Actual Total Performances (ATP)
|
||||
by tracking unique listeners across all song plays. All other information is derived from the metadata of the
|
||||
uploaded songs themselves, and may not be completely accurate.</li>
|
||||
<li>Reporting requirements for SoundExchange may change at any time. AzuraCast is non-commercial community-built
|
||||
software and cannot guarantee that its reporting format will always be up-to-date.</li>
|
||||
<li>You should always verify the report generated by AzuraCast before sending it. In particular, either the ISRC
|
||||
(International Standard Recording Code) or *both* the album and label are required for every row, and may not be
|
||||
provided in the song metadata. To locate an ISRC for a track, you should use
|
||||
<a href="https://isrc.soundexchange.com" target="_blank">SoundExchange\'s ISRC search tool</a>.</li>
|
||||
</ul>',
|
||||
]
|
||||
],
|
||||
|
||||
'start_date' => [
|
||||
'text',
|
||||
[
|
||||
'type' => 'date',
|
||||
'label' => _('Report Start Date'),
|
||||
'required' => true,
|
||||
]
|
||||
],
|
||||
|
||||
'end_date' => [
|
||||
'text',
|
||||
[
|
||||
'type' => 'date',
|
||||
'label' => _('Report End Date'),
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
|
||||
'fetch_isrc' => [
|
||||
'toggle',
|
||||
[
|
||||
'label' => __('Attempt to Automatically Retrieve ISRC When Missing'),
|
||||
'description' => __(
|
||||
'If enabled, AzuraCast will connect to the MusicBrainz database to attempt to find an ISRC for any files where one is missing. Disabling this may improve performance.'
|
||||
),
|
||||
'selected_text' => __('Yes'),
|
||||
'deselected_text' => __('No'),
|
||||
'default' => true,
|
||||
],
|
||||
],
|
||||
|
||||
'submit' => [
|
||||
'submit',
|
||||
[
|
||||
'type' => 'submit',
|
||||
'label' => _('Generate Report'),
|
||||
'class' => 'btn btn-lg btn-primary',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
];
|
|
@ -104,7 +104,7 @@ return static function (RouteCollectorProxy $app) {
|
|||
$group->map(
|
||||
['GET', 'POST'],
|
||||
'/soundexchange',
|
||||
Controller\Stations\Reports\SoundExchangeController::class
|
||||
Controller\Stations\Reports\SoundExchangeAction::class
|
||||
)
|
||||
->setName('stations:reports:soundexchange');
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
<b-alert variant="danger" :show="error != null">{{ error }}</b-alert>
|
||||
|
||||
<form id="login-form" action="" method="post">
|
||||
<form id="login-form" class="form vue-form" action="" method="post">
|
||||
<input type="hidden" name="csrf" :value="csrf"/>
|
||||
|
||||
<b-wrapped-form-group id="username" name="username" label-class="mb-2" :field="$v.form.username"
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<section class="card" role="region">
|
||||
<div class="card-header bg-primary-dark">
|
||||
<h3 class="card-title">
|
||||
<translate key="hdr">SoundExchange Report</translate>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<form id="report-form" class="form vue-form" method="POST" action="">
|
||||
<input type="hidden" name="csrf" :value="csrf"/>
|
||||
|
||||
<div class="card-body">
|
||||
<b-form-fieldset>
|
||||
<p>This report is intended for licensing in the United States only, for webcasters paying royalties
|
||||
via SoundExchange. Learn more about the requirements for reporting and classification on the
|
||||
<a href="https://www.soundexchange.com/service-provider/reporting-requirements/"
|
||||
target="_blank">
|
||||
SoundExchange web site
|
||||
</a>.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>AzuraCast assumes that your station fits SoundExchange Transmission Category A, "Eligible
|
||||
nonsubscription transmissions other than broadcast simulcasts and transmissions of non-music
|
||||
programming." If your station does not fall within this category, update the transmission
|
||||
category field accordingly.
|
||||
<li>The data collected by AzuraCast meets the SoundExchange standard for Actual Total
|
||||
Performances (ATP) by tracking unique listeners across all song plays. All other information
|
||||
is derived from the metadata of the uploaded songs themselves, and may not be completely
|
||||
accurate.
|
||||
</li>
|
||||
<li>Reporting requirements for SoundExchange may change at any time. AzuraCast is non-commercial
|
||||
community-built software and cannot guarantee that its reporting format will always be
|
||||
up-to-date.
|
||||
</li>
|
||||
<li>You should always verify the report generated by AzuraCast before sending it. In particular,
|
||||
either the ISRC (International Standard Recording Code) or *both* the album and label are
|
||||
required for every row, and may not be provided in the song metadata. To locate an ISRC for
|
||||
a track, you should use <a href="https://isrc.soundexchange.com" target="_blank">SoundExchange's
|
||||
ISRC search tool</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</b-form-fieldset>
|
||||
|
||||
<b-form-fieldset>
|
||||
<b-wrapped-form-group name="start_date" id="form_start_date" :field="$v.form.start_date"
|
||||
input-type="date">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Start Date</translate>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-group name="end_date" id="form_end_date" :field="$v.form.end_date"
|
||||
input-type="date">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">End Date</translate>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-checkbox name="fetch_isrc" id="form_edit_fetch_isrc" :field="$v.form.fetch_isrc">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Attempt to Automatically Retrieve ISRC When Missing</translate>
|
||||
</template>
|
||||
<template #description="{lang}">
|
||||
<translate :key="lang">If enabled, AzuraCast will connect to the MusicBrainz database to attempt to find an ISRC for any files where one is missing. Disabling this may improve performance.</translate>
|
||||
</template>
|
||||
</b-wrapped-form-checkbox>
|
||||
</b-form-fieldset>
|
||||
|
||||
<b-button type="submit" size="lg" variant="primary" class="mt-2" :disabled="$v.form.$invalid">
|
||||
<translate key="btn_submit">Generate Report</translate>
|
||||
</b-button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from "~/components/Common/Icon";
|
||||
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
|
||||
import {validationMixin} from "vuelidate";
|
||||
import {required} from 'vuelidate/dist/validators.min.js';
|
||||
import BFormFieldset from "~/components/Form/BFormFieldset";
|
||||
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
|
||||
|
||||
export default {
|
||||
name: 'StationsReportsSoundExchange',
|
||||
props: {
|
||||
csrf: String,
|
||||
startDate: String,
|
||||
endDate: String
|
||||
},
|
||||
components: {Icon, BWrappedFormGroup, BFormFieldset, BWrappedFormCheckbox},
|
||||
mixins: [
|
||||
validationMixin
|
||||
],
|
||||
validations() {
|
||||
return {
|
||||
form: {
|
||||
start_date: {required},
|
||||
end_date: {required},
|
||||
fetch_isrc: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
start_date: this.startDate,
|
||||
end_date: this.endDate,
|
||||
fetch_isrc: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,8 @@
|
|||
import initBase from '~/base.js';
|
||||
|
||||
import '~/vendor/bootstrapVue.js';
|
||||
import '~/vendor/luxon.js';
|
||||
|
||||
import SoundExchange from '~/components/Stations/Reports/SoundExchange.vue';
|
||||
|
||||
export default initBase(SoundExchange);
|
|
@ -43,6 +43,7 @@ module.exports = {
|
|||
StationsReportsRequests: '~/pages/Stations/Reports/Requests.js',
|
||||
StationsReportsOverview: '~/pages/Stations/Reports/Overview.js',
|
||||
StationsReportsPerformance: '~/pages/Stations/Reports/Performance.js',
|
||||
StationsReportsSoundExchange: '~/pages/Stations/Reports/SoundExchange.js',
|
||||
StationsReportsTimeline: '~/pages/Stations/Reports/Timeline.js',
|
||||
StationsSftpUsers: '~/pages/Stations/SftpUsers.js',
|
||||
StationsWebhooks: '~/pages/Stations/Webhooks.js'
|
||||
|
|
|
@ -4,9 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Stations\Reports;
|
||||
|
||||
use App\Config;
|
||||
use App\Entity;
|
||||
use App\Form\Form;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Service\MusicBrainz;
|
||||
|
@ -18,42 +16,36 @@ use Throwable;
|
|||
/**
|
||||
* Produce a report in SoundExchange (the US webcaster licensing agency) format.
|
||||
*/
|
||||
class SoundExchangeController
|
||||
class SoundExchangeAction
|
||||
{
|
||||
protected array $form_config;
|
||||
|
||||
public function __construct(
|
||||
protected EntityManagerInterface $em,
|
||||
protected MusicBrainz $musicBrainz,
|
||||
Config $config
|
||||
protected MusicBrainz $musicBrainz
|
||||
) {
|
||||
$this->form_config = $config->get('forms/report/soundexchange');
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
||||
$tzObject = $station->getTimezoneObject();
|
||||
|
||||
$startDate = CarbonImmutable::parse('first day of last month', $tzObject);
|
||||
$endDate = CarbonImmutable::parse('last day of last month', $tzObject);
|
||||
$csrf = $request->getCsrf();
|
||||
|
||||
$form = new Form($this->form_config);
|
||||
$form->populate(
|
||||
[
|
||||
'start_date' => $startDate->format('Y-m-d'),
|
||||
'end_date' => $endDate->format('Y-m-d'),
|
||||
]
|
||||
);
|
||||
$defaultStartDate = CarbonImmutable::parse('first day of last month', $tzObject)->format('Y-m-d');
|
||||
$defaultEndDate = CarbonImmutable::parse('last day of last month', $tzObject)->format('Y-m-d');
|
||||
|
||||
if ($form->isValid($request)) {
|
||||
$data = $form->getValues();
|
||||
if ($request->isPost()) {
|
||||
$data = (array)$request->getParsedBody();
|
||||
|
||||
$csrf->verify($data['csrf'] ?? '', 'soundexchange');
|
||||
|
||||
$data['start_date'] ??= $defaultStartDate;
|
||||
$data['end_date'] ??= $defaultEndDate;
|
||||
|
||||
$startDate = CarbonImmutable::parse($data['start_date'] . ' 00:00:00', $tzObject);
|
||||
$endDate = CarbonImmutable::parse($data['end_date'] . ' 23:59:59', $tzObject);
|
||||
|
||||
$fetchIsrc = $data['fetch_isrc'];
|
||||
$fetchIsrc = 'true' === ($data['fetch_isrc'] ?? 'false');
|
||||
|
||||
$export = [
|
||||
[
|
||||
|
@ -99,6 +91,7 @@ class SoundExchangeController
|
|||
->setParameter('time_end', $endDate->getTimestamp())
|
||||
->getArrayResult();
|
||||
|
||||
// TODO: Fix this (not all song rows have a media_id)
|
||||
$history_rows_by_id = array_column($history_rows, null, 'media_id');
|
||||
|
||||
// Remove any reference to the "Stream Offline" song.
|
||||
|
@ -163,11 +156,17 @@ class SoundExchangeController
|
|||
return $response->renderStringAsFile($export_txt, 'text/plain', $export_filename);
|
||||
}
|
||||
|
||||
return $request->getView()->renderToResponse($response, 'system/form_page', [
|
||||
'form' => $form,
|
||||
'render_mode' => 'edit',
|
||||
'title' => __('SoundExchange Report'),
|
||||
]);
|
||||
return $request->getView()->renderVuePage(
|
||||
response: $response,
|
||||
component: 'Vue_StationsReportsSoundExchange',
|
||||
id: 'station-report-soundexchange',
|
||||
title: __('SoundExchange Report'),
|
||||
props: [
|
||||
'csrf' => $csrf->generate('soundexchange'),
|
||||
'startDate' => $defaultStartDate,
|
||||
'endDate' => $defaultEndDate,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function findISRC(array $song_row): ?string
|
|
@ -41,11 +41,5 @@ class Station_ReportsCest extends CestAbstract
|
|||
$I->amOnPage('/station/' . $station_id . '/reports/soundexchange');
|
||||
$I->seeResponseCodeIs(200);
|
||||
$I->see('SoundExchange Report');
|
||||
|
||||
$I->submitForm(
|
||||
'form#azuraforms_form',
|
||||
['azuraforms_form_start_date' => '11/01/2020', 'azuraforms_form_end_date' => '11/30/2020']
|
||||
);
|
||||
$I->seeResponseCodeIs(200);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue