Move admin/custom fields to Vue.
This commit is contained in:
parent
aeb230e0bd
commit
6eaeaec023
|
@ -1,118 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'method' => 'post',
|
||||
'groups' => [
|
||||
[
|
||||
'use_grid' => true,
|
||||
'elements' => [
|
||||
|
||||
'name' => [
|
||||
'text',
|
||||
[
|
||||
'label' => __('Field Name'),
|
||||
'description' => __('This will be used as the label when editing individual songs, and will show in API results.'),
|
||||
'form_group_class' => 'col-md-6',
|
||||
],
|
||||
],
|
||||
|
||||
'short_name' => [
|
||||
'text',
|
||||
[
|
||||
'label' => __('Programmatic Name'),
|
||||
'description' => __('Optionally specify an API-friendly name, such as <code>field_name</code>. Leave this field blank to automatically create one based on the name.'),
|
||||
'form_group_class' => 'col-md-6',
|
||||
],
|
||||
],
|
||||
|
||||
'auto_assign' => [
|
||||
'select',
|
||||
[
|
||||
'label' => __('Automatically Set from ID3v2 Value'),
|
||||
'description' => __('Optionally select an ID3v2 metadata field that, if present, will be used to set this field\'s value.'),
|
||||
'default' => '',
|
||||
'form_group_class' => 'col-md-6',
|
||||
'options' => [
|
||||
'' => __('Disable'),
|
||||
'album' => __('Album'), // TAL, TALB
|
||||
'album_artist_sort_order' => __('Album Artist Sort Order'), // TS2, TSO2
|
||||
'album_sort_order' => __('Album Sort Order'), // TSA, TSOA
|
||||
'artist' => __('Artist'), // TP1, TPE1
|
||||
'band' => __('Band'), // TP2, TPE2
|
||||
'bpm' => __('Bpm'), // TBP, TBPM
|
||||
'comment' => __('Comment'), // COM, COMM
|
||||
'commercial_information' => __('Commercial Information'), // WCM, WCOM
|
||||
'composer' => __('Composer'), // TCM, TCOM
|
||||
'composer_sort_order' => __('Composer Sort Order'), // TSC, TSOC
|
||||
'conductor' => __('Conductor'), // TP3, TPE3
|
||||
'content_group_description' => __('Content Group Description'), // TIT1, TT1
|
||||
'copyright' => __('Copyright'), // WCOP, WCP
|
||||
'copyright_message' => __('Copyright Message'), // TCOP, TCR
|
||||
'encoded_by' => __('Encoded By'), // TEN, TENC
|
||||
'encoder_settings' => __('Encoder Settings'), // TSS, TSSE
|
||||
'encoding_time' => __('Encoding Time'), // TDEN
|
||||
'file_owner' => __('File Owner'), // TOWN
|
||||
'file_type' => __('File Type'), // TFLT, TFT
|
||||
'genre' => __('Genre'), // TCO, TCON
|
||||
'initial_key' => __('Initial Key'), // TKE, TKEY
|
||||
'internet_radio_station_name' => __('Internet Radio Station Name'), // TRSN
|
||||
'internet_radio_station_owner' => __('Internet Radio Station Owner'), // TRSO
|
||||
'involved_people_list' => __('Involved People List'), // IPL, IPLS, TIPL
|
||||
'isrc' => __('ISRC'), // TRC, TSRC
|
||||
'language' => __('Language'), // TLA, TLAN
|
||||
'length' => __('Length'), // TLE, TLEN
|
||||
'linked_information' => __('Linked Information'), // LINK, LNK
|
||||
'lyricist' => __('Lyricist'), // TEXT, TXT
|
||||
'media_type' => __('Media Type'), // TMED, TMT
|
||||
'mood' => __('Mood'), // TMOO
|
||||
'music_cd_identifier' => __('Music CD Identifier'), // MCDI, MCI
|
||||
'musician_credits_list' => __('Musician Credits List'), // TMCL
|
||||
'original_album' => __('Original Album'), // TOAL, TOT
|
||||
'original_artist' => __('Original Artist'), // TOA, TOPE
|
||||
'original_filename' => __('Original Filename'), // TOF, TOFN
|
||||
'original_lyricist' => __('Original Lyricist'), // TOL, TOLY
|
||||
'original_release_time' => __('Original Release Time'), // TDOR
|
||||
'original_year' => __('Original Year'), // TOR, TORY
|
||||
'part_of_a_compilation' => __('Part Of A Compilation'), // TCMP, TCP
|
||||
'part_of_a_set' => __('Part Of A Set'), // TPA, TPOS
|
||||
'performer_sort_order' => __('Performer Sort Order'), // TSOP, TSP
|
||||
'playlist_delay' => __('Playlist Delay'), // TDLY, TDY
|
||||
'produced_notice' => __('Produced Notice'), // TPRO
|
||||
'publisher' => __('Publisher'), // TPB, TPUB
|
||||
'recording_time' => __('Recording Time'), // TDRC
|
||||
'release_time' => __('Release Time'), // TDRL
|
||||
'remixer' => __('Remixer'), // TP4, TPE4
|
||||
'set_subtitle' => __('Set Subtitle'), // TSST
|
||||
'subtitle' => __('Subtitle'), // TIT3, TT3
|
||||
'tagging_time' => __('Tagging Time'), // TDTG
|
||||
'terms_of_use' => __('Terms Of Use'), // USER
|
||||
'title' => __('Title'), // TIT2, TT2
|
||||
'title_sort_order' => __('Title Sort Order'), // TSOT, TST
|
||||
'track_number' => __('Track Number'), // TRCK, TRK
|
||||
'unsynchronised_lyric' => __('Unsynchronised Lyric'), // ULT, USLT
|
||||
'url_artist' => __('URL Artist'), // WAR, WOAR
|
||||
'url_file' => __('URL File'), // WAF, WOAF
|
||||
'url_payment' => __('URL Payment'), // WPAY
|
||||
'url_publisher' => __('URL Publisher'), // WPB, WPUB
|
||||
'url_source' => __('URL Source'), // WAS, WOAS
|
||||
'url_station' => __('URL Station'), // WORS
|
||||
'url_user' => __('URL User'), // WXX, WXXX
|
||||
'year' => __('Year'), // TYE, TYER
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'submit' => [
|
||||
'submit',
|
||||
[
|
||||
'type' => 'submit',
|
||||
'label' => __('Save Changes'),
|
||||
'class' => 'btn btn-lg btn-primary',
|
||||
'form_group_class' => 'col-sm-12',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
|
@ -115,26 +115,9 @@ return static function (RouteCollectorProxy $app) {
|
|||
->setName('admin:branding:index')
|
||||
->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS));
|
||||
|
||||
$group->group(
|
||||
'/custom_fields',
|
||||
function (RouteCollectorProxy $group) {
|
||||
$group->get('', Controller\Admin\CustomFieldsController::class . ':indexAction')
|
||||
->setName('admin:custom_fields:index');
|
||||
|
||||
$group->map(
|
||||
['GET', 'POST'],
|
||||
'/edit/{id}',
|
||||
Controller\Admin\CustomFieldsController::class . ':editAction'
|
||||
)
|
||||
->setName('admin:custom_fields:edit');
|
||||
|
||||
$group->map(['GET', 'POST'], '/add', Controller\Admin\CustomFieldsController::class . ':editAction')
|
||||
->setName('admin:custom_fields:add');
|
||||
|
||||
$group->get('/delete/{id}/{csrf}', Controller\Admin\CustomFieldsController::class . ':deleteAction')
|
||||
->setName('admin:custom_fields:delete');
|
||||
}
|
||||
)->add(new Middleware\Permissions(Acl::GLOBAL_CUSTOM_FIELDS));
|
||||
$group->get('/custom_fields', Controller\Admin\CustomFieldsAction::class)
|
||||
->setName('admin:custom_fields:index')
|
||||
->add(new Middleware\Permissions(Acl::GLOBAL_CUSTOM_FIELDS));
|
||||
|
||||
$group->group(
|
||||
'/logs',
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
<template>
|
||||
<div>
|
||||
<b-card no-body>
|
||||
<b-card-header header-bg-variant="primary-dark">
|
||||
<h2 class="card-title" key="lang_title" v-translate>Custom Fields</h2>
|
||||
</b-card-header>
|
||||
|
||||
<info-card>
|
||||
<p class="card-text">
|
||||
<translate key="lang_card_info">Create custom fields to store extra metadata about each media file uploaded to your station libraries.</translate>
|
||||
</p>
|
||||
</info-card>
|
||||
|
||||
<b-card-body body-class="card-padding-sm">
|
||||
<b-button variant="outline-primary" @click.prevent="doCreate">
|
||||
<icon icon="add"></icon>
|
||||
<translate key="lang_add_btn">Add Custom Field</translate>
|
||||
</b-button>
|
||||
</b-card-body>
|
||||
|
||||
<data-table ref="datatable" id="custom_fields" :fields="fields" :show-toolbar="false" :api-url="listUrl">
|
||||
<template #cell(name)="row">
|
||||
{{ row.item.name }} <code>{{ row.item.short_name }}</code>
|
||||
</template>
|
||||
<template #cell(auto_assign)="row">
|
||||
{{ getAutoAssignName(row.item.auto_assign) }}
|
||||
</template>
|
||||
<template #cell(actions)="row">
|
||||
<b-button-group size="sm">
|
||||
<b-button size="sm" variant="primary" @click.prevent="doEdit(row.item.links.self)">
|
||||
<translate key="lang_btn_edit">Edit</translate>
|
||||
</b-button>
|
||||
<b-button size="sm" variant="danger" @click.prevent="doDelete(row.item.links.self)">
|
||||
<translate key="lang_btn_delete">Delete</translate>
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
</template>
|
||||
</data-table>
|
||||
</b-card>
|
||||
|
||||
<edit-modal ref="editModal" :create-url="listUrl" :auto-assign-types="autoAssignTypes"
|
||||
@relist="relist"></edit-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DataTable from '~/components/Common/DataTable';
|
||||
import EditModal from './CustomFields/EditModal';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import InfoCard from '~/components/Common/InfoCard';
|
||||
import handleAxiosError from '~/functions/handleAxiosError';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'AdminCustomFields',
|
||||
components: {InfoCard, Icon, EditModal, DataTable},
|
||||
props: {
|
||||
listUrl: String,
|
||||
autoAssignTypes: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fields: [
|
||||
{key: 'name', isRowHeader: true, label: this.$gettext('Field Name'), sortable: false},
|
||||
{key: 'auto_assign', label: this.$gettext('Auto-Assign Value'), sortable: false},
|
||||
{key: 'actions', label: this.$gettext('Actions'), sortable: false, class: 'shrink'}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getAutoAssignName(autoAssign) {
|
||||
return _.get(this.autoAssignTypes, autoAssign, this.$gettext('None'));
|
||||
},
|
||||
relist() {
|
||||
this.$refs.datatable.refresh();
|
||||
},
|
||||
doCreate() {
|
||||
this.$refs.editModal.create();
|
||||
},
|
||||
doEdit(url) {
|
||||
this.$refs.editModal.edit(url);
|
||||
},
|
||||
doDelete(url) {
|
||||
let buttonText = this.$gettext('Delete');
|
||||
let buttonConfirmText = this.$gettext('Delete Custom Field?');
|
||||
|
||||
Swal.fire({
|
||||
title: buttonConfirmText,
|
||||
confirmButtonText: buttonText,
|
||||
confirmButtonColor: '#e64942',
|
||||
showCancelButton: true,
|
||||
focusCancel: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
this.axios.delete(url).then((resp) => {
|
||||
notify('<b>' + resp.data.message + '</b>', 'success');
|
||||
|
||||
this.relist();
|
||||
}).catch((err) => {
|
||||
handleAxiosError(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<b-modal size="lg" id="edit_modal" ref="modal" :title="langTitle" :busy="loading">
|
||||
<b-overlay variant="card" :show="loading">
|
||||
<b-alert variant="danger" :show="error != null">{{ error }}</b-alert>
|
||||
|
||||
<b-form class="form" @submit.prevent="doSubmit">
|
||||
<b-tabs content-class="mt-3">
|
||||
<admin-custom-fields-form :form="$v.form" :auto-assign-types="autoAssignTypes">
|
||||
</admin-custom-fields-form>
|
||||
</b-tabs>
|
||||
|
||||
<invisible-submit-button/>
|
||||
</b-form>
|
||||
</b-overlay>
|
||||
<template #modal-footer>
|
||||
<b-button variant="default" type="button" @click="close">
|
||||
<translate key="lang_btn_close">Close</translate>
|
||||
</b-button>
|
||||
<b-button variant="primary" type="submit" @click="doSubmit" :disabled="$v.form.$invalid">
|
||||
<translate key="lang_btn_save_changes">Save Changes</translate>
|
||||
</b-button>
|
||||
</template>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {validationMixin} from 'vuelidate';
|
||||
import {required} from 'vuelidate/dist/validators.min.js';
|
||||
import InvisibleSubmitButton from '~/components/Common/InvisibleSubmitButton';
|
||||
import BaseEditModal from '~/components/Common/BaseEditModal';
|
||||
import AdminCustomFieldsForm from "~/components/Admin/CustomFields/Form";
|
||||
|
||||
export default {
|
||||
name: 'AdminCustomFieldsEditModal',
|
||||
components: {AdminCustomFieldsForm, InvisibleSubmitButton},
|
||||
mixins: [validationMixin, BaseEditModal],
|
||||
props: {
|
||||
autoAssignTypes: Object
|
||||
},
|
||||
computed: {
|
||||
langTitle() {
|
||||
return this.isEditMode
|
||||
? this.$gettext('Edit Custom Field')
|
||||
: this.$gettext('Add Custom Field');
|
||||
}
|
||||
},
|
||||
validations() {
|
||||
return {
|
||||
form: {
|
||||
'name': {required},
|
||||
'short_name': {},
|
||||
'auto_assign': {}
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetForm() {
|
||||
this.form = {
|
||||
'name': '',
|
||||
'short_name': '',
|
||||
'auto_assign': ''
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,69 @@
|
|||
<template>
|
||||
<b-form-group>
|
||||
<b-row>
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_name" :field="form.name">
|
||||
<template #label>
|
||||
<translate key="lang_form_name">Field Name</translate>
|
||||
</template>
|
||||
<template #description>
|
||||
<translate key="lang_form_name_desc">This will be used as the label when editing individual songs, and will show in API results.</translate>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_short_name" :field="form.short_name">
|
||||
<template #label>
|
||||
<translate key="lang_form_short_name">Programmatic Name</translate>
|
||||
</template>
|
||||
<template #description>
|
||||
<translate key="lang_form_short_name_desc">Optionally specify an API-friendly name, such as "field_name". Leave this field blank to automatically create one based on the name.</translate>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_auto_assign" :field="form.auto_assign">
|
||||
<template #label>
|
||||
<translate key="lang_form_auto_assign">Automatically Set from ID3v2 Value</translate>
|
||||
</template>
|
||||
<template #description>
|
||||
<translate key="lang_form_auto_assign_desc">Optionally select an ID3v2 metadata field that, if present, will be used to set this field's value.</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-select :id="props.id" v-model="props.field.$model"
|
||||
:options="autoAssignOptions"></b-form-select>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
</b-row>
|
||||
</b-form-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'AdminCustomFieldsForm',
|
||||
components: {BWrappedFormGroup},
|
||||
props: {
|
||||
form: Object,
|
||||
autoAssignTypes: Object
|
||||
},
|
||||
computed: {
|
||||
autoAssignOptions() {
|
||||
let autoAssignOptions = [
|
||||
{
|
||||
text: this.$gettext('Disable'),
|
||||
value: '',
|
||||
}
|
||||
];
|
||||
|
||||
_.forEach(this.autoAssignTypes, (typeName, typeKey) => {
|
||||
autoAssignOptions.push({
|
||||
text: typeName,
|
||||
value: typeKey
|
||||
});
|
||||
});
|
||||
|
||||
return autoAssignOptions;
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -33,7 +33,7 @@ import {required} from 'vuelidate/dist/validators.min.js';
|
|||
import InvisibleSubmitButton from '~/components/Common/InvisibleSubmitButton';
|
||||
import BaseEditModal from '~/components/Common/BaseEditModal';
|
||||
import AdminPermissionsGlobalForm from "./Form/GlobalForm";
|
||||
import AdminPermissionsStationForm from "~/components/Admin/Permissions/Form/StationForm";
|
||||
import AdminPermissionsStationForm from "./Form/StationForm";
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
<template>
|
||||
<b-select :value="value" @input="this.$emit('input', $event.target.value)" v-bind="$attrs"
|
||||
:class="{ 'select2-hidden-accessible': true }" plain>
|
||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
||||
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
|
||||
<slot :name="name" v-bind="slotData"/>
|
||||
</template>
|
||||
</b-select>
|
||||
</template>
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'BSelect2',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: {},
|
||||
selectOptions: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
$(this.$el)
|
||||
.select2(this.allSelectOptions)
|
||||
.val(this.value);
|
||||
},
|
||||
computed: {
|
||||
allSelectOptions () {
|
||||
let options = _.clone(this.selectOptions);
|
||||
_.defaults(options, {
|
||||
width: '100%',
|
||||
theme: 'bootstrap4',
|
||||
language: App.lang.locale_short
|
||||
});
|
||||
return options;
|
||||
}
|
||||
},
|
||||
destroyed: function () {
|
||||
$(this.$el)
|
||||
.off()
|
||||
.select2('destroy');
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
import '~/base.js';
|
||||
import '~/vendor/bootstrapVue.js';
|
||||
|
||||
import Vue
|
||||
from 'vue';
|
||||
|
||||
import AdminCustomFields
|
||||
from '~/components/Admin/CustomFields.vue';
|
||||
|
||||
export default function (el, props) {
|
||||
return new Vue({
|
||||
el: el,
|
||||
render: (createElement) => {
|
||||
return createElement(AdminCustomFields, {
|
||||
props: props
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -9,6 +9,7 @@ module.exports = {
|
|||
Dashboard: '~/pages/Dashboard.js',
|
||||
AdminAuditLog: '~/pages/Admin/AuditLog.js',
|
||||
AdminBranding: '~/pages/Admin/Branding.js',
|
||||
AdminCustomFields: '~/pages/Admin/CustomFields.js',
|
||||
AdminPermissions: '~/pages/Admin/Permissions.js',
|
||||
AdminStorageLocations: '~/pages/Admin/StorageLocations.js',
|
||||
PublicFullPlayer: '~/pages/Public/FullPlayer.js',
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class CustomFieldsAction
|
||||
{
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response
|
||||
): ResponseInterface {
|
||||
$router = $request->getRouter();
|
||||
|
||||
return $request->getView()->renderToResponse(
|
||||
$response,
|
||||
'system/vue',
|
||||
[
|
||||
'title' => __('Custom Fields'),
|
||||
'id' => 'admin-custom-fields',
|
||||
'component' => 'Vue_AdminCustomFields',
|
||||
'props' => [
|
||||
'listUrl' => (string)$router->fromHere('api:admin:custom_fields'),
|
||||
'autoAssignTypes' => [
|
||||
'album' => __('Album'), // TAL, TALB
|
||||
'album_artist_sort_order' => __('Album Artist Sort Order'), // TS2, TSO2
|
||||
'album_sort_order' => __('Album Sort Order'), // TSA, TSOA
|
||||
'artist' => __('Artist'), // TP1, TPE1
|
||||
'band' => __('Band'), // TP2, TPE2
|
||||
'bpm' => __('Bpm'), // TBP, TBPM
|
||||
'comment' => __('Comment'), // COM, COMM
|
||||
'commercial_information' => __('Commercial Information'), // WCM, WCOM
|
||||
'composer' => __('Composer'), // TCM, TCOM
|
||||
'composer_sort_order' => __('Composer Sort Order'), // TSC, TSOC
|
||||
'conductor' => __('Conductor'), // TP3, TPE3
|
||||
'content_group_description' => __('Content Group Description'), // TIT1, TT1
|
||||
'copyright' => __('Copyright'), // WCOP, WCP
|
||||
'copyright_message' => __('Copyright Message'), // TCOP, TCR
|
||||
'encoded_by' => __('Encoded By'), // TEN, TENC
|
||||
'encoder_settings' => __('Encoder Settings'), // TSS, TSSE
|
||||
'encoding_time' => __('Encoding Time'), // TDEN
|
||||
'file_owner' => __('File Owner'), // TOWN
|
||||
'file_type' => __('File Type'), // TFLT, TFT
|
||||
'genre' => __('Genre'), // TCO, TCON
|
||||
'initial_key' => __('Initial Key'), // TKE, TKEY
|
||||
'internet_radio_station_name' => __('Internet Radio Station Name'), // TRSN
|
||||
'internet_radio_station_owner' => __('Internet Radio Station Owner'), // TRSO
|
||||
'involved_people_list' => __('Involved People List'), // IPL, IPLS, TIPL
|
||||
'isrc' => __('ISRC'), // TRC, TSRC
|
||||
'language' => __('Language'), // TLA, TLAN
|
||||
'length' => __('Length'), // TLE, TLEN
|
||||
'linked_information' => __('Linked Information'), // LINK, LNK
|
||||
'lyricist' => __('Lyricist'), // TEXT, TXT
|
||||
'media_type' => __('Media Type'), // TMED, TMT
|
||||
'mood' => __('Mood'), // TMOO
|
||||
'music_cd_identifier' => __('Music CD Identifier'), // MCDI, MCI
|
||||
'musician_credits_list' => __('Musician Credits List'), // TMCL
|
||||
'original_album' => __('Original Album'), // TOAL, TOT
|
||||
'original_artist' => __('Original Artist'), // TOA, TOPE
|
||||
'original_filename' => __('Original Filename'), // TOF, TOFN
|
||||
'original_lyricist' => __('Original Lyricist'), // TOL, TOLY
|
||||
'original_release_time' => __('Original Release Time'), // TDOR
|
||||
'original_year' => __('Original Year'), // TOR, TORY
|
||||
'part_of_a_compilation' => __('Part Of A Compilation'), // TCMP, TCP
|
||||
'part_of_a_set' => __('Part Of A Set'), // TPA, TPOS
|
||||
'performer_sort_order' => __('Performer Sort Order'), // TSOP, TSP
|
||||
'playlist_delay' => __('Playlist Delay'), // TDLY, TDY
|
||||
'produced_notice' => __('Produced Notice'), // TPRO
|
||||
'publisher' => __('Publisher'), // TPB, TPUB
|
||||
'recording_time' => __('Recording Time'), // TDRC
|
||||
'release_time' => __('Release Time'), // TDRL
|
||||
'remixer' => __('Remixer'), // TP4, TPE4
|
||||
'set_subtitle' => __('Set Subtitle'), // TSST
|
||||
'subtitle' => __('Subtitle'), // TIT3, TT3
|
||||
'tagging_time' => __('Tagging Time'), // TDTG
|
||||
'terms_of_use' => __('Terms Of Use'), // USER
|
||||
'title' => __('Title'), // TIT2, TT2
|
||||
'title_sort_order' => __('Title Sort Order'), // TSOT, TST
|
||||
'track_number' => __('Track Number'), // TRCK, TRK
|
||||
'unsynchronised_lyric' => __('Unsynchronised Lyric'), // ULT, USLT
|
||||
'url_artist' => __('URL Artist'), // WAR, WOAR
|
||||
'url_file' => __('URL File'), // WAF, WOAF
|
||||
'url_payment' => __('URL Payment'), // WPAY
|
||||
'url_publisher' => __('URL Publisher'), // WPB, WPUB
|
||||
'url_source' => __('URL Source'), // WAS, WOAS
|
||||
'url_station' => __('URL Station'), // WORS
|
||||
'url_user' => __('URL User'), // WXX, WXXX
|
||||
'year' => __('Year'), // TYE, TYER
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity;
|
||||
use App\Form\CustomFieldForm;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Session\Flash;
|
||||
use DI\FactoryInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class CustomFieldsController extends AbstractAdminCrudController
|
||||
{
|
||||
public function __construct(FactoryInterface $factory)
|
||||
{
|
||||
parent::__construct($factory->make(CustomFieldForm::class));
|
||||
|
||||
$this->csrf_namespace = 'admin_custom_fields';
|
||||
}
|
||||
|
||||
public function indexAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$records = $this->em->createQueryBuilder()
|
||||
->select('e')
|
||||
->from(Entity\CustomField::class, 'e')
|
||||
->orderBy('e.name')
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
return $request->getView()->renderToResponse($response, 'admin/custom_fields/index', [
|
||||
'records' => $records,
|
||||
'csrf' => $request->getCsrf()->generate($this->csrf_namespace),
|
||||
]);
|
||||
}
|
||||
|
||||
public function editAction(ServerRequest $request, Response $response, int $id = null): ResponseInterface
|
||||
{
|
||||
if (false !== $this->doEdit($request, $id)) {
|
||||
$request->getFlash()->addMessage(
|
||||
($id ? __('Custom Field updated.') : __('Custom Field added.')),
|
||||
Flash::SUCCESS
|
||||
);
|
||||
return $response->withRedirect((string)$request->getRouter()->named('admin:custom_fields:index'));
|
||||
}
|
||||
|
||||
return $request->getView()->renderToResponse(
|
||||
$response,
|
||||
'system/form_page',
|
||||
[
|
||||
'form' => $this->form,
|
||||
'render_mode' => 'edit',
|
||||
'title' => $id ? __('Edit Custom Field') : __('Add Custom Field'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function deleteAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
int $id,
|
||||
string $csrf
|
||||
): ResponseInterface {
|
||||
$this->doDelete($request, $id, $csrf);
|
||||
|
||||
$request->getFlash()->addMessage('<b>' . __('Custom Field deleted.') . '</b>', Flash::SUCCESS);
|
||||
|
||||
return $response->withRedirect((string)$request->getRouter()->named('admin:custom_fields:index'));
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Config;
|
||||
use App\Entity;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
class CustomFieldForm extends EntityForm
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
ValidatorInterface $validator,
|
||||
Config $config
|
||||
) {
|
||||
$form_config = $config->get('forms/custom_field');
|
||||
parent::__construct($em, $serializer, $validator, $form_config);
|
||||
|
||||
$this->entityClass = Entity\CustomField::class;
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
<?php $this->layout('main', ['title' => __('Custom Fields'), 'manual' => true]); ?>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary-dark">
|
||||
<h2 class="card-title"><?=__('Custom Fields') ?></h2>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<a class="btn btn-outline-primary" role="button" href="<?=$router->named('admin:custom_fields:add') ?>">
|
||||
<i class="material-icons" aria-hidden="true">add</i>
|
||||
<?=__('Add Custom Field') ?>
|
||||
</a>
|
||||
</div>
|
||||
<table class="table table-responsive-md table-striped mb-0">
|
||||
<colgroup>
|
||||
<col width="30%">
|
||||
<col width="40%">
|
||||
<col width="30%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?=__('Actions') ?></th>
|
||||
<th><?=__('Name') ?></th>
|
||||
<th><?=__('Programmatic Name') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($records as $row): ?>
|
||||
<tr class="align-middle">
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a class="btn btn-sm btn-primary" href="<?=$router->named('admin:custom_fields:edit', ['id' => $row['id']]) ?>"><?=__('Edit') ?></a>
|
||||
<a class="btn btn-sm btn-danger" data-confirm-title="<?=$this->e(__('Delete custom field "%s"?', $row['name'])) ?>" href="<?=$router->named('admin:custom_fields:delete', ['id' => $row['id'], 'csrf' => $csrf]) ?>"><?=__('Delete') ?></a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<?=$this->e($row['name']) ?>
|
||||
</td>
|
||||
<td>
|
||||
<?=$this->e($row['short_name']) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
Loading…
Reference in New Issue