Merge remote-tracking branch 'origin/master' into master

This commit is contained in:
vedatakd 2021-05-03 09:33:49 +03:00
commit de41bba043
111 changed files with 4124 additions and 337 deletions

View File

@ -0,0 +1,35 @@
<?php
use Anomaly\Streams\Platform\Database\Migration\Migration;
class VisiosoftModuleAdvsChangeProductOptionsValue extends Migration
{
public function __construct()
{
//Maria DB will be removed when the version is updated.
\Illuminate\Support\Facades\DB::getDoctrineSchemaManager()
->getDatabasePlatform()->registerDoctrineTypeMapping('point', 'string');
}
public function up()
{
if (!$field = $this->fields()->findBySlugAndNamespace('product_options_value', 'advs')) {
return;
}
$field->setAttribute('type', 'visiosoft.field_type.multiple');
$this->fields()->save($field);
}
public function down()
{
if (!$field = $this->fields()->findBySlugAndNamespace('product_options_value', 'advs')) {
return;
}
$field->setAttribute('type', 'anomaly.field_type.multiple');
$this->fields()->save($field);
}
}

View File

@ -18,12 +18,12 @@ return [
'tcmb_exchange_url',
'enabled_currencies',
'disable_sentry',
'hide_ad_cat',
],
],
'ads' => [
'title' => 'visiosoft.module.advs::section.ads',
'fields' => [
'detailed_product_options',
'latest-limit',
'popular_ads_limit',
'ads_image_limit',
@ -52,6 +52,7 @@ return [
'create_ad' => [
'title' => 'visiosoft.module.advs::section.create_ad',
'fields' => [
'detailed_product_options',
'steps_color',
'create_ad_button_color',
'hide_standard_price_field',

View File

@ -449,4 +449,10 @@ return [
'default_value' => false,
]
],
'hide_ad_cat' => [
'type' => 'anomaly.field_type.boolean',
'config' => [
'default_value' => false,
]
],
];

View File

@ -0,0 +1,262 @@
/* Main styles */
html {
font-size: 12px;
@media only screen and (min-width: 576px) {
font-size: 7.5789px;
}
@media only screen and (min-width: 768px) {
font-size: 10.1052px;
}
@media only screen and (min-width: 992px) {
font-size: 13.4736px;
}
@media only screen and (min-width: 1200px) {
font-size: 16px;
}
}
label {
margin-bottom: 0;
}
/* End Main styles */
#pageTitle {
margin: 2rem 0;
@media only screen and (min-width: 576px) {
margin: 4rem 0;
}
h1 {
font-weight: 700;
}
h2 {
color: #707070;
font-size: calc(24rem / 16);
font-weight: 400;
}
}
#contactInfo {
background-color: #FBFBFD;
padding: 1.4rem 1rem 1.5rem;
@media only screen and (min-width: 576px) {
padding: 2.4rem 4rem 5.5rem;
}
h3 {
color: #6E5DDB;
font-size: calc(26rem / 16);
margin-bottom: 2rem;
}
#reachInfo {
font-family: 'Poppins', sans-serif;
margin-bottom: 2rem;
p {
color: #4A4A4A;
font-size: calc(14rem / 16);
font-weight: 600;
}
div {
label {
color: #505050;
font-size: calc(18rem / 16);
font-weight: 500;
}
}
}
#contactSummary {
font-family: 'Poppins', sans-serif;
margin-bottom: 1rem;
@media only screen and (min-width: 576px) {
margin-bottom: 2rem;
}
label {
font-size: calc(14rem / 16);
color: #4A4A4A;
width: 100%;
font-weight: 600;
margin-bottom: 1rem;
@media only screen and (min-width: 576px) {
width: 32.4%;
margin-bottom: 0;
}
input {
box-shadow: 0 calc(1rem / 16) calc(2rem / 16) rgba(0, 0, 0, .04);
font-size: calc(17rem / 16);
padding: 1.1rem 1.5rem;
color: #707070;
}
}
}
#editContact {
button {
color: #0075FF;
background: none;
font-size: calc(18rem / 16);
svg {
height: 1.08rem;
width: auto;
}
span {
margin-left: .75rem;
}
}
}
}
#mainInfo {
background-color: #FBFBFD;
padding: 1.4rem 1rem 2.3rem;
@media only screen and (min-width: 576px) {
padding: 2.4rem 4rem 4.3rem;
}
h3 {
color: #6E5DDB;
font-size: calc(26rem / 16);
margin-bottom: 2rem;
}
label {
font-family: 'Poppins', sans-serif;
font-size: calc(14rem / 16);
color: #4A4A4A;
font-weight: 600;
input {
box-shadow: 0 calc(1rem / 16) calc(2rem / 16) rgba(0, 0, 0, .04);
font-size: calc(17rem / 16);
padding: 1.1rem 1.5rem;
color: #707070;
}
}
#stockInput {
flex-wrap: wrap;
@media only screen and (min-width: 576px) {
flex-wrap: nowrap;
}
& > label {
width: 100%;
@media only screen and (min-width: 576px) {
width: 47.5%;
}
&:not(.d-none) + div {
top: .6rem;
}
&.d-none + div {
margin-bottom: .5rem;
}
}
div {
position: relative;
margin: 1rem 0;
@media only screen and (min-width: 576px) {
margin: 0;
width: 47.5%;
}
svg {
width: 2.2rem;
height: auto;
}
label {
position: relative;
top: .25rem;
font-weight: 500;
font-size: calc(16rem / 16);
}
}
}
#priceInput {
& > div {
::placeholder {
color: #B9C0CF;
opacity: 1;
}
:-ms-input-placeholder {
color: #B9C0CF;
}
::-ms-input-placeholder {
color: #B9C0CF;
}
input, select {
box-shadow: 0 calc(1rem / 16) calc(2rem / 16) rgba(0, 0, 0, .04);
font-size: calc(17rem / 16);
padding: 1.1rem 1.5rem;
color: #707070;
}
&:first-child {
@media only screen and (min-width: 576px) {
width: 47.5%;
}
input {
&.decimal-price {
width: 17%;
}
}
}
&:last-child {
@media only screen and (min-width: 576px) {
width: 50.75%;
}
select, .decimal-price {
width: 17%;
}
select {
padding: 1.1rem 1rem;
}
}
}
}
#simpleOptionsInput {
.select2-selection {
box-shadow: 0 calc(1rem / 16) calc(2rem / 16) rgba(0, 0, 0, .04);
font-size: calc(17rem / 16);
padding: 1.1rem 1.5rem;
color: #707070;
border: 0;
margin-top: 1rem;
.select2-selection__rendered {
padding: 0;
display: flex;
margin: 0;
flex-wrap: wrap;
.select2-selection__choice {
float: none;
}
.select2-search__field {
padding: 0;
}
}
}
}
}

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14.212" height="14.148" viewBox="0 0 14.212 14.148">
<path id="Path_11030" data-name="Path 11030" d="M-1636.669-813.08l-.773.772-7.73,7.731-.006.006a.582.582,0,0,0-.1.159c-.007.015-.011.029-.017.045s-.016.041-.022.063l-.828,3.92a.681.681,0,0,0-.008.094c0,.007,0,.012,0,.019v.009a.508.508,0,0,0,.039.182c.005.013.01.026.017.039a.535.535,0,0,0,.1.153.542.542,0,0,0,.387.164h13.119a.546.546,0,0,0,.547-.546.546.546,0,0,0-.547-.546h-8.707l7.626-7.626.773-.772a2.732,2.732,0,0,0-.01-3.857,2.721,2.721,0,0,0-1.931-.8A2.724,2.724,0,0,0-1636.669-813.08Zm-7.791,9.989.833.834.833.832-2.112.447Zm1.607.061-1.16-1.16,6.958-6.957,1.159,1.16,1.159,1.159-6.957,6.957Zm6.57-8.89.387-.387a1.682,1.682,0,0,1,2.319,0,1.643,1.643,0,0,1,0,2.32l-.387.386Z" transform="translate(1646.16 813.872)" fill="#0075ff"/>
</svg>

After

Width:  |  Height:  |  Size: 850 B

View File

@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="28.064" height="24.555" viewBox="0 0 28.064 24.555">
<g id="credit-card" transform="translate(0 -32.008)">
<g id="Group_16590" data-name="Group 16590" transform="translate(0 37.269)">
<g id="Group_16589" data-name="Group 16589" transform="translate(0 0)">
<path id="Path_11024" data-name="Path 11024" d="M12.278,129.746v-1.754H1.754A1.757,1.757,0,0,0,0,129.746v3.508H12.648A15.7,15.7,0,0,1,12.278,129.746Z" transform="translate(0 -127.992)" fill="#7a50f0"/>
</g>
</g>
<g id="Group_16592" data-name="Group 16592" transform="translate(0 46.039)">
<g id="Group_16591" data-name="Group 16591">
<path id="Path_11025" data-name="Path 11025" d="M27.992,287.992a15.776,15.776,0,0,1-5.634,4.913,2.635,2.635,0,0,1-2.615,0,15.855,15.855,0,0,1-5.636-4.916H0v8.77a1.756,1.756,0,0,0,1.754,1.754H26.31a1.755,1.755,0,0,0,1.754-1.754v-8.77Zm-20.1,5.262H4.385a.877.877,0,0,1,0-1.754H7.893a.877.877,0,0,1,0,1.754Z" transform="translate(0 -287.992)" fill="#7a50f0"/>
</g>
</g>
<g id="Group_16594" data-name="Group 16594" transform="translate(14.032 32.008)">
<g id="Group_16593" data-name="Group 16593" transform="translate(0 0)">
<path id="Path_11026" data-name="Path 11026" d="M269.5,34.71l-6.139-2.631a.88.88,0,0,0-.693,0L256.53,34.71a.875.875,0,0,0-.53.805v3.508c0,4.825,1.784,7.646,6.579,10.408a.882.882,0,0,0,.873,0c4.8-2.756,6.579-5.576,6.579-10.408V35.515A.874.874,0,0,0,269.5,34.71ZM266.333,38.7l-3.508,4.385a.887.887,0,0,1-.686.328H262.1a.88.88,0,0,1-.693-.389l-1.754-2.631a.877.877,0,1,1,1.459-.972l1.089,1.633,2.757-3.448a.877.877,0,0,1,1.372,1.094Z" transform="translate(-256 -32.008)" fill="#7a50f0"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -11,14 +11,21 @@ $('.formEditInfo').on('submit', function (e) {
$.ajax({
type: 'POST',
data: form.serialize() + "&action=update",
data: {
action: 'update',
first_name: $('input[name=first_name]', form).val(),
last_name: $('input[name=last_name]', form).val(),
gsm_phone: $('#gsm_phone', form).val(),
office_phone: $('#office_phone', form).val(),
land_phone: $('#land_phone', form).val(),
},
url: '/ajax/update-user-info',
success: function (response) {
if (response.status == "success") {
var profile = response.data;
$('.infoName').html(profile.first_name + " " + profile.last_name);
$('.infoGsmPhone').html(profile.gsm_phone);
$('.infoOfficePhone').html(profile.office_phone);
$('.infoName').val(profile.first_name + " " + profile.last_name);
$('.infoGsmPhone').val(profile.gsm_phone);
$('.infoOfficePhone').val(profile.office_phone);
$('.infoLandPhone').html(profile.land_phone);
$('#editMyInfo').modal('hide');

View File

@ -336,6 +336,7 @@ return [
'ad_location' => 'موقع الإعلان',
'owner' => 'صاحب',
'default_owner_instruction' => 'سيتحول المالك إلى المستخدم الحالي افتراضيًا إذا لم يتم تحديد أي مستخدم',
'create_page_subtitle' => 'قم بإنشاء الإعلان بشكل لا تشوبه شائبة عن طريق إدخال معلومات مفصلة حول إعلانك.',
// Listing page
'ad_title' => 'عنوان الاعلان',
@ -343,7 +344,7 @@ return [
'view' => 'منظر',
'ads_with_map' => 'الإعلانات مع الخريطة',
'advanced_sorting' => 'الفرز المتقدم',
'filter_by_word' => 'Filter by word',
'filter_by_word' => 'تصفية بالكلمة',
'free' => 'مجانا',
'ad_date' => 'تاريخ الإعلان',
@ -367,4 +368,5 @@ return [
'old_price' => [
'name' => 'سعر قديم'
],
'save_search' => 'حفظ البحث',
];

View File

@ -264,5 +264,12 @@ return [
],
'show_subcats_mobile' => [
'name' => 'إظهار الفئات الفرعية على طريقة عرض الجوال',
]
],
'show_price_to_members_only' => [
'name' => 'عرض السعر للأعضاء فقط',
],
'hide_ad_cat' => [
'name' => 'إخفاء الفئات',
'instructions' => 'إخفاء الفئات في قائمة الإعلانات'
]
];

View File

@ -337,6 +337,7 @@ return [
'ad_location' => 'Anzeigenposition',
'owner' => 'Inhaber',
'default_owner_instruction' => 'Der Eigentümer verwendet standardmäßig den aktuellen Benutzer, wenn kein Benutzer ausgewählt ist',
'create_page_subtitle' => 'Erstellen Sie die Anzeige fehlerfrei, indem Sie detaillierte Informationen zu Ihrer Anzeige eingeben.',
// Listing page
'ad_title' => 'Anzeigentitel',
@ -344,7 +345,7 @@ return [
'view' => 'Aussicht',
'ads_with_map' => 'Anzeigen mit Karte',
'advanced_sorting' => 'Erweiterte Sortierung',
'filter_by_word' => 'Filter by word',
'filter_by_word' => 'Nach Wort filtern',
'free' => 'Frei',
'ad_date' => 'Anzeigedatum',
@ -368,4 +369,5 @@ return [
'old_price' => [
'name' => 'Alter Preis'
],
'save_search' => 'Sichere Suche',
];

View File

@ -264,5 +264,12 @@ return [
],
'show_subcats_mobile' => [
'name' => 'Unterkategorien in der mobilen Ansicht anzeigen',
]
],
'show_price_to_members_only' => [
'name' => 'Preis nur für Mitglieder anzeigen',
],
'hide_ad_cat' => [
'name' => 'Kategorien ausblenden',
'instructions' => 'Kategorien in der Anzeigenliste ausblenden'
]
];

View File

@ -336,6 +336,7 @@ return [
'ad_location' => 'Ad Location',
'owner' => 'Owner',
'default_owner_instruction' => 'The owner will default to the current user if no user is selected',
'create_page_subtitle' => 'Create the ad flawlessly by entering detailed information about your ad.',
// Listing page
'ad_title' => 'Ad title',
@ -367,4 +368,5 @@ return [
'old_price' => [
'name' => 'Old Price'
],
'save_search' => 'Save Search',
];

View File

@ -268,4 +268,8 @@ return [
'show_price_to_members_only' => [
'name' => 'Show Price To Members Only',
],
'hide_ad_cat' => [
'name' => 'Hide Categories',
'instructions' => 'Hide categories in ads list'
]
];

View File

@ -337,6 +337,7 @@ return [
'ad_location' => 'Emplacement de l\'annonce',
'owner' => 'Propriétaire',
'default_owner_instruction' => 'Le propriétaire utilisera par défaut l\'utilisateur actuel si aucun utilisateur n\'est sélectionné',
'create_page_subtitle' => 'Créez parfaitement l\'annonce en saisissant des informations détaillées sur votre annonce.',
// Listing page
'ad_title' => 'Ajouter un titre',
@ -344,7 +345,7 @@ return [
'view' => 'Vue',
'ads_with_map' => 'Annonces avec carte',
'advanced_sorting' => 'Tri avancé',
'filter_by_word' => 'Filter by word',
'filter_by_word' => 'Filtrer par mot',
'free' => 'Gratuit',
'ad_date' => 'Date de l\'annonce',
@ -368,4 +369,5 @@ return [
'old_price' => [
'name' => 'Ancien prix'
],
'save_search' => 'Sauvegarder la recherche',
];

View File

@ -264,5 +264,12 @@ return [
],
'show_subcats_mobile' => [
'name' => 'Afficher les sous-catégories sur la vue mobile',
]
],
'show_price_to_members_only' => [
'name' => 'Afficher le prix aux membres seulement',
],
'hide_ad_cat' => [
'name' => 'Masquer les catégories',
'instructions' => 'Masquer les catégories dans la liste des annonces'
]
];

View File

@ -336,6 +336,7 @@ return [
'ad_location' => 'Hirdetés helye',
'owner' => 'Tulajdonos',
'default_owner_instruction' => 'A tulajdonos alapértelmezés szerint az aktuális felhasználót állítja be, ha nincs kiválasztva felhasználó',
'create_page_subtitle' => 'Hozza létre a hirdetést hibátlanul a hirdetésével kapcsolatos részletes információk megadásával.',
// Listing page
'ad_title' => 'Hirdetés címe',
@ -343,7 +344,7 @@ return [
'view' => 'Kilátás',
'ads_with_map' => 'Hirdetések térképpel',
'advanced_sorting' => 'Haladó rendezés',
'filter_by_word' => 'Filter by word',
'filter_by_word' => 'Szűrés szó szerint',
'free' => 'Ingyenes',
'ad_date' => 'Hirdetés dátuma',
@ -367,4 +368,5 @@ return [
'old_price' => [
'name' => 'Régi ár'
],
'save_search' => 'Keresés mentése',
];

View File

@ -264,5 +264,12 @@ return [
],
'show_subcats_mobile' => [
'name' => 'Alkategóriák megjelenítése mobil nézetben',
]
],
'show_price_to_members_only' => [
'name' => 'Árak megjelenítése csak tagoknak',
],
'hide_ad_cat' => [
'name' => 'Kategóriák elrejtése',
'instructions' => 'Kategóriák elrejtése a hirdetési listában'
]
];

View File

@ -338,6 +338,7 @@ return [
'ad_location' => 'İlan Konumu',
'owner' => 'Sahip',
'default_owner_instruction' => 'Hiçbir kullanıcı seçilmezse, sahip varsayılan olarak mevcut kullanıcıyı kullanır',
'create_page_subtitle' => 'Ürün veya ilan hakkında detaylı bilgi girebilirsiniz',
// Listing page
'ad_title' => 'Başlık',
@ -369,4 +370,5 @@ return [
'old_price' => [
'name' => 'Eski fiyat'
],
'save_search' => 'Aramayı Kaydet',
];

View File

@ -264,5 +264,12 @@ return [
],
'show_subcats_mobile' => [
'name' => 'Alt kategorileri mobil görünümde göster',
]
],
'show_price_to_members_only' => [
'name' => 'Sadece Üyelere Fiyat Göster',
],
'hide_ad_cat' => [
'name' => 'Kategorileri Gizle',
'instructions' => 'İlan listelemede ilan kategorilerini gizle'
]
];

View File

@ -1,6 +1,5 @@
<div class="slider-text">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 offered-field offered-row
{{ setting_value('visiosoft.module.advs::show_price_to_members_only') ? (not auth_check() ? 'd-none') }}">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 offered-field offered-row">
{% set standardPrice = adv.standard_price.value %}
{% if standardPrice and standardPrice > 0 %}
<div class="d-flex flex-wrap align-items-center">

View File

@ -28,7 +28,9 @@
<h6 class="mb-1">
<a href="{{ adv.detail_url }}">{{ adv.name }}</a>
</h6>
<p class="cat-data mb-1">{{ adv.cat1_name }} /{{ adv.cat2_name }}</p>
{% if not setting_value('visiosoft.module.advs::hide_ad_cat') %}
<p class="cat-data mb-1">{{ adv.cat1_name }} /{{ adv.cat2_name }}</p>
{% endif %}
{% if showPrice %}
<p class="price-data mb-1">
{{ adv.price != '0' ? currency_format(adv.price,adv.currency) : trans('visiosoft.module.advs::field.free') }}

View File

@ -27,7 +27,7 @@
</p>
<a href="javascript:void(0)" class="d-flex align-items-center fav-search-modal">
<span class="mr-2">Save Search</span>
<span class="mr-2">{{ trans('visiosoft.module.advs::field.save_search') }}</span>
{{ img('visiosoft.module.advs::images/listing/save-search.svg').data|raw }}
</a>
</div>

View File

@ -35,7 +35,9 @@
<h6 class="mb-1">
<a href="{{ adv.detail_url }}">{{ adv.name }}</a>
</h6>
<p class="cat-data mb-1">{{ adv.cat1_name }} /{{ adv.cat2_name }}</p>
{% if not setting_value('visiosoft.module.advs::hide_ad_cat') %}
<p class="cat-data mb-1">{{ adv.cat1_name }} /{{ adv.cat2_name }}</p>
{% endif %}
<div class="action-data d-flex align-items-center">
{{ addBlock('list/extra-actions', {'ad': adv, 'vars': _context})|raw }}

View File

@ -14,11 +14,13 @@
{{ img('visiosoft.module.advs::images/listing/list.svg').data|raw }}
<p class="ml-2">{{ trans("visiosoft.module.advs::field.list") }}</p>
</a>
<a href="{{ url_route('visiosoft.module.advs::view_type', ['map']) }}" rel="nofollow"
class="d-flex w-50 align-items-center pr-2 pb-1 justify-content-end{{ request().cookie.viewType == "map" ? ' active' }}">
{{ img('visiosoft.module.advs::images/listing/map.svg').data|raw }}
<p class="ml-2">{{ trans("visiosoft.module.advs::field.map.name") }}</p>
</a>
{% if setting_value('visiosoft.module.location::list_page_location') %}
<a href="{{ url_route('visiosoft.module.advs::view_type', ['map']) }}" rel="nofollow"
class="d-flex w-50 align-items-center pr-2 pb-1 justify-content-end{{ request().cookie.viewType == "map" ? ' active' }}">
{{ img('visiosoft.module.advs::images/listing/map.svg').data|raw }}
<p class="ml-2">{{ trans("visiosoft.module.advs::field.map.name") }}</p>
</a>
{% endif %}
</div>
{% include 'visiosoft.module.cats::ads-list/partials/cat-filter' %}

View File

@ -1,7 +1,18 @@
{% extends layout('new-create') %}
{% block styles %}
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<style>
{{ asset_inline("visiosoft.module.advs::css/new-create.css") }}
{{ asset_inline("visiosoft.module.advs::css/new-create-new.scss") }}
</style>
{% endblock %}
{% block content %}
<section class="clearfix home-default">
{% include 'visiosoft.module.advs::new-ad/partials/steps' with {'step': 'new-create'} %}
<div>
@ -17,6 +28,12 @@
</li>
</ol>
</nav>
<div id="pageTitle" class="text-center">
<h1 class="mb-3">{{ trans('visiosoft.module.advs::field.listing_details') }}</h1>
<h2>{{ trans('visiosoft.module.advs::field.create_page_subtitle') }}</h2>
</div>
<div class="adpost-details">
<div class="row">
<div class="col-md-12">
@ -48,125 +65,107 @@
{% include 'visiosoft.module.advs::new-ad/partials/contact-info' %}
<h5 class="mt-5 pb-1 border-bottom">{{ trans('visiosoft.module.advs::field.ad_info') }}</h5>
<div class="section postdetails bg-light p-4">
<div class="row form-group add-title">
{% set fields = form.fields.base().pluck('field_name').all() %}
<div class="col-md-12">
<div class="field-group name">
{% for field in form.fields.translations('name') %}
{{ field.render({'form': form})|raw }}
{% endfor %}
</div>
</div>
<div id="mainInfo">
<h3>{{ trans('visiosoft.module.advs::field.ad_info') }}</h3>
<div style="display: none">
{{ form.fields.slug|raw }}
</div>
</div>
<label class="w-100 mb-2">
{% set fields = form.fields.base().pluck('field_name').all() %}
{% for field in form.fields.translations('name') %}
{{ field.setAttributes({
'class': 'd-block mt-3 w-100 border-0'
}).render({'form': form})|raw }}
{% endfor %}
</label>
{% if setting_value('visiosoft.module.advs::market_place') %}
{{ addBlock('new-ad/fields', {'adv': adv})|raw }}
{% endif %}
<div class="row form-group select-price
{{ setting_value('visiosoft.module.advs::hide_standard_price_field') ? ' d-none' }}
{{ setting_value('visiosoft.module.advs::market_place') != true ? 'd-none' }}">
<label class="col-sm-2 col-xs-12">
{{ form.fields.standard_price.label|raw }}
<span class="required">*</span>
</label>
<div class="col-12 standard-price-hidden d-none">
{{ form.fields.standard_price.setAttributes({
'required' :true
}).input|raw }}
</div>
{% set standardPriceValue = form.fields.standard_price.value|split('.') %}
<div class="col-8 pr-0 col-md-3">
<input class="form-control standard-price-field whole-price"
value="{{ standardPriceValue|first }}">
</div>
<div class="col-4 col-md-1">
<input class="form-control standard-price-decimal-field decimal-price"
placeholder="00" maxlength="2"
value="{{ standardPriceValue[1] }}">
</div>
</div>
<div class="row form-group select-price{{ hidePrice ? ' hidden' }}">
<div id="priceInput" class="d-flex justify-content-between mb-4 flex-wrap">
<div class="mb-3 mb-sm-0 select-price{{ hidePrice ? ' hidden' }}">
<label>
{{ form.fields.price.label|raw }}
<span class="required">*</span>
</label>
<label class="col-sm-2 col-xs-12">
{{ form.fields.price.label|raw }}
<span class="required">*</span>
</label>
<div class="col-12 priceHidden d-none">
{{ form.fields.price.setAttributes({
'required' :true
}).input|raw }}
</div>
{% set PriceValue = form.fields.price.value|split('.') %}
<div class="col-6 col-sm-7 pr-0 col-md-3">
<input class="form-control priceField whole-price"
value="{{ PriceValue|first }}">
</div>
{% if setting_value('visiosoft.field_type.decimal::showDecimal') %}
<div class="col-4 col-md-1">
<input class="form-control priceDecimalField decimal-price" placeholder="00"
maxlength="2"
value="{{ PriceValue[1] }}">
<div class="col-12 priceHidden d-none">
{{ form.fields.price.setAttributes({
'required' :true
}).input|raw }}
</div>
{% endif %}
<div class="col-sm-3 col-6">
<select name="currency" class="custom-select form-control" data-field="currency"
data-field_name="currency" data-provides="anomaly.field_type.select"
id="currency" required="">
{% for currency in config_get('streams::currencies.enabled') %}
<option value="{{ currency }}">
{% if currency == "TRY" %}
{{ currency_symbol(currency) }}
{% else %}
{{ currency }}
{% endif %}
</option>
{% endfor %}
</select>
<div class="d-flex">
{% set PriceValue = form.fields.price.value|split('.') %}
<input type="text" class="mt-3 border-0 text-right priceField whole-price flex-fill"
placeholder="0" value="{{ PriceValue|first }}">
{% if setting_value('visiosoft.field_type.decimal::showDecimal') %}
<input class="mt-3 border-0 ml-2 text-center priceDecimalField decimal-price"
placeholder="00" type="text" value="{{ PriceValue[1] }}">
{% endif %}
</div>
</div>
<div class="select-price{{ setting_value('visiosoft.module.advs::hide_standard_price_field') or setting_value('visiosoft.module.advs::market_place') != true ? ' d-none' }}">
<label>
{{ form.fields.standard_price.label }}
<span class="required">*</span>
</label>
<div class="col-12 standard-price-hidden d-none">
{{ form.fields.standard_price.setAttributes({
'required' :true
}).input|raw }}
</div>
<div class="d-flex">
{% set standardPriceValue = form.fields.standard_price.value|split('.') %}
<input class="mt-3 border-0 text-right standard-price-field whole-price flex-fill"
placeholder="0" value="{{ standardPriceValue|first }}" type="text">
{% if setting_value('visiosoft.field_type.decimal::showDecimal') %}
<input class="mt-3 border-0 ml-2 text-center standard-price-decimal decimal-price"
placeholder="00" type="text" value="{{ standardPriceValue[1] }}" maxlength="2">
{% endif %}
<select name="currency" class="mt-3 border-0 ml-2" id="currency" required>
{% for currency in config_get('streams::currencies.enabled') %}
<option value="{{ currency }}">
{{ currency == "TRY" ? currency_symbol(currency) : currency }}
</option>
{% endfor %}
</select>
</div>
</div>
</div>
{% if not setting_value('visiosoft.module.advs::hide_options_field') %}
{% if not setting_value('visiosoft.module.advs::detailed_product_options') %}
<div class="row form-group select-options">
<label for="selectOptions" class="col-sm-2">
<div id="simpleOptionsInput" class="w-100 select-options">
<label for="selectOptions">
{{ trans('visiosoft.module.advs::field.options') }}
</label>
<div class="col-sm-10">
<select id="selectOptions" class="form-control options-tags"
multiple="multiple"
name="options[]">
{% if count(options) %}
{% for option in options %}
<option id="advOption{{ option.id }}"
selected="selected">{{ option.name }}</option>
{% endfor %}
{% endif %}
</select>
</div>
{% if auth_check() and auth_user().hasRole('admin') %}
<div class="col-12 text-right py-2">
<p class="text-muted">
<i class="fa fa-exclamation-triangle"></i>
{{ trans('visiosoft.module.advs::message.disabled_detailed_options_for_admin_role') }}
</p>
</div>
{% endif %}
<select id="selectOptions" type="text" multiple="multiple" name="options[]"
class="d-block mt-3 w-100 border-0 options-tags">
{% if count(options) %}
{% for option in options %}
<option id="advOption{{ option.id }}"
selected="selected">{{ option.name }}</option>
{% endfor %}
{% endif %}
</select>
</div>
{% if auth_check() and auth_user().hasRole('admin') %}
<div class="col-12 text-right py-2">
<p class="text-muted d-flex align-items-center justify-content-end">
<i class="fa fa-exclamation-triangle mr-2"></i>
{{ trans('visiosoft.module.advs::message.disabled_detailed_options_for_admin_role') }}
</p>
</div>
{% endif %}
{% else %}
<div class="row form-group product-options">
<label for="productOptions" class="col-sm-2">
<div class="product-options">
<label for="productOptions">
{{ trans('visiosoft.module.advs::field.product_option.name') }}
</label>
<div class="col-sm-10">
{{ form.fields.product_options_value.configSet('cat1',adv.cat1).input|raw }}
<div class="mt-3 form-group mb-0">
{{ form.fields.product_options_value.configSet('cat1', adv.cat1).input|raw }}
</div>
</div>
{% endif %}
@ -275,6 +274,5 @@
{{ asset_add("scripts.js", "visiosoft.module.advs::js/new-create.js") }}
{{ asset_add("scripts.js", "streams::js/form/form.js") }}
{{ asset_add("scripts.js", "streams::js/form/translations.js") }}
{{ asset_add("styles.css", "visiosoft.module.advs::css/new-create.css") }}
{% endblock %}

View File

@ -1,47 +1,40 @@
<h5 class="pb-1 border-bottom">{{ trans('visiosoft.module.advs::field.contact_info') }}</h5>
<div class="px-3 bg-light row justify-content-center m-0">
<div class="col-md-9 col-lg-7 border my-4 bg-white py-3 row m-0 px-0 editContact rounded">
<div class="col-12 row m-0 border-bottom py-2">
<div class="col-12 col-md-4 pl-0">
<label class="mb-0 font-weight-bold">
{{ trans('visiosoft.module.profile::field.first_name.name') }}
{{ trans('visiosoft.module.profile::field.last_name.name') }}:
</label>
</div>
<div class="col-12 col-md-8 infoName">
{{ getProfileDetail(auth_user().id).first_name }}
{{ getProfileDetail(auth_user().id).last_name }}
</div>
</div>
<div class="col-12 row m-0 border-bottom py-1">
<div class="col-12 col-md-4 pl-0">
<label class="mb-0 font-weight-bold">{{ trans('visiosoft.module.profile::field.gsm_phone.name') }}</label>
</div>
<div class="col-12 col-md-8 infoGsmPhone">
{{ getProfileDetail(auth_user().id).gsm_phone }}
</div>
</div>
<div class="col-12 row m-0 border-bottom py-1">
<div class="col-12 col-md-4 pl-0">
<label class="mb-0 font-weight-bold">{{ trans('visiosoft.module.profile::field.office_phone.name') }}</label>
</div>
<div class="col-12 col-md-8 infoOfficePhone">
{{ getProfileDetail(auth_user().id).office_phone }}
</div>
</div>
<div class="col-12 row m-0 py-1">
<div class="col-12 col-md-4 pl-0">
<label class="mb-0 font-weight-bold">{{ trans('visiosoft.module.profile::field.land_phone.name') }}</label>
</div>
<div class="col-12 col-md-8 infoLandPhone">
{{ getProfileDetail(auth_user().id).land_phone }}
</div>
</div>
<p class="px-3 py-2">
<a href="#" class="editInformationUser">
<i class="fas fa-pen"></i>
{{ trans('visiosoft.module.advs::field.update_my_contact_info') }}
</a>
</p>
<div id="contactInfo" class="mb-3">
<h3>{{ trans('visiosoft.module.advs::field.contact_info') }}</h3>
{# TODO Add an option to show or hide phone number #}
{# <div id="reachInfo">#}
{# <p>Size nasıl ulaşılsın?</p>#}
{# <div>#}
{# <label class="mr-3">#}
{# <input type="radio" class="mr-1" checked>#}
{# Telefon numaralarım ile#}
{# </label>#}
{# <label>#}
{# <input type="radio" class="mr-1">#}
{# Telefonla ulaşılmak istemiyorum#}
{# </label>#}
{# </div>#}
{# </div>#}
<div id="contactSummary" class="d-flex justify-content-between flex-wrap">
<label>
{{ trans('visiosoft.module.profile::field.name.name') }}
<input type="text" class="d-block mt-3 w-100 border-0 bg-white infoName" value="{{ auth_user().name }}"
disabled>
</label>
<label>
{{ trans('visiosoft.module.profile::field.gsm_phone.name') }}
<input type="text" class="d-block mt-3 w-100 border-0 bg-white infoGsmPhone" disabled
value="{{ auth_user().gsm_phone }}">
</label>
<label>
{{ trans('visiosoft.module.profile::field.office_phone.name') }}
<input type="text" class="d-block mt-3 w-100 border-0 bg-white infoOfficePhone" disabled
value="{{ auth_user().office_phone }}">
</label>
</div>
</div>
<div id="editContact">
<button type="button" class="d-flex ml-auto align-items-center border-0 editInformationUser">
{{ img('visiosoft.module.advs::images/create/contact-edit.svg').data|raw }}
<span>{{ trans('visiosoft.module.advs::field.update_my_contact_info') }}</span>
</button>
</div>
</div>

View File

@ -9,24 +9,14 @@ class AdvFormBuilder extends FormBuilder
protected $category = null;
protected $rules = [];
protected $skips = [
'slug'
];
protected $actions = [];
protected $buttons = [
'cancel',
];
protected $options = [];
protected $sections = [];
protected $assets = [];
public function __construct(Form $form)
{
parent::__construct($form);

View File

@ -4,7 +4,7 @@ use Anomaly\Streams\Platform\Ui\Table\Table;
use Visiosoft\AdvsModule\Productoption\Contract\ProductoptionRepositoryInterface;
use Visiosoft\AdvsModule\ProductoptionsValue\Contract\ProductoptionsValueRepositoryInterface;
class LookupTableBuilder extends \Anomaly\MultipleFieldType\Table\LookupTableBuilder
class LookupTableBuilder extends \Visiosoft\MultipleFieldType\Table\LookupTableBuilder
{
public function __construct(Table $table,ValueTableBuilder $valueTableBuilder)
{

View File

@ -1,6 +1,6 @@
<?php namespace Visiosoft\AdvsModule\ProductoptionsValue\Support\MultipleFieldType;
class SelectedTableBuilder extends \Anomaly\MultipleFieldType\Table\SelectedTableBuilder
class SelectedTableBuilder extends \Visiosoft\MultipleFieldType\Table\SelectedTableBuilder
{
protected $columns = [
'name', 'product_option'

View File

@ -1,6 +1,6 @@
<?php namespace Visiosoft\AdvsModule\ProductoptionsValue\Support\MultipleFieldType;
class ValueTableBuilder extends \Anomaly\MultipleFieldType\Table\ValueTableBuilder
class ValueTableBuilder extends \Visiosoft\MultipleFieldType\Table\ValueTableBuilder
{
protected $columns = [
'name', 'product_option'

View File

@ -48,7 +48,9 @@ class Currency
$decimals = 0;
}
}
if (setting_value('visiosoft.module.advs::show_price_to_members_only') && !auth()->check()){
return null;
}
return $prefix . number_format($number, $decimals, $point, str_replace('&#160;', ' ', $separator)) . $suffix;
}

View File

@ -1,167 +1,15 @@
<?php namespace Visiosoft\BaseTheme;
use Anomaly\Streams\Platform\Addon\AddonServiceProvider;
use Illuminate\Routing\Router;
class BaseThemeServiceProvider extends AddonServiceProvider
{
/**
* Additional addon plugins.
*
* @type array|null
*/
protected $plugins = [];
/**
* The addon Artisan commands.
*
* @type array|null
*/
protected $commands = [];
/**
* The addon's scheduled commands.
*
* @type array|null
*/
protected $schedules = [];
/**
* The addon API routes.
*
* @type array|null
*/
protected $api = [];
/**
* The addon routes.
*
* @type array|null
*/
protected $routes = [];
/**
* The addon middleware.
*
* @type array|null
*/
protected $middleware = [
//Visiosoft\TestbootTheme\Http\Middleware\ExampleMiddleware::class
];
/**
* Addon group middleware.
*
* @var array
*/
protected $groupMiddleware = [
//'web' => [
// Visiosoft\TestbootTheme\Http\Middleware\ExampleMiddleware::class,
//],
];
/**
* Addon route middleware.
*
* @type array|null
*/
protected $routeMiddleware = [];
/**
* The addon event listeners.
*
* @type array|null
*/
protected $listeners = [
//Visiosoft\TestbootTheme\Event\ExampleEvent::class => [
// Visiosoft\TestbootTheme\Listener\ExampleListener::class,
//],
];
/**
* The addon alias bindings.
*
* @type array|null
*/
protected $aliases = [
//'Example' => Visiosoft\TestbootTheme\Example::class
];
/**
* The addon class bindings.
*
* @type array|null
*/
protected $bindings = [];
/**
* The addon singleton bindings.
*
* @type array|null
*/
protected $singletons = [];
/**
* Additional service providers.
*
* @type array|null
*/
protected $providers = [
//\ExamplePackage\Provider\ExampleProvider::class
];
/**
* The addon view overrides.
*
* @type array|null
*/
protected $overrides = [
//'streams::errors/404' => 'module::errors/404',
//'streams::errors/500' => 'module::errors/500',
];
/**
* The addon mobile-only view overrides.
*
* @type array|null
*/
protected $mobile = [
'streams::errors/404' => 'visiosoft.theme.base::errors/404',
'streams::errors/403' => 'visiosoft.theme.base::errors/403',
'anomaly.module.users::login' => 'visiosoft.theme.base::addons/anomaly/users-module/login',
'anomaly.module.users::register' => 'visiosoft.theme.base::addons/anomaly/users-module/register',
'anomaly.module.users::password/forgot' => 'visiosoft.theme.base::addons/anomaly/users-module/password/forgot',
'anomaly.module.users::password/reset' => 'visiosoft.theme.base::addons/anomaly/users-module/password/reset'
'anomaly.module.users::password/reset' => 'visiosoft.theme.base::addons/anomaly/users-module/password/reset',
];
/**
* Register the addon.
*/
public function register()
{
// Run extra pre-boot registration logic here.
// Use method injection or commands to bring in services.
}
/**
* Boot the addon.
*/
public function boot()
{
// Run extra post-boot registration logic here.
// Use method injection or commands to bring in services.
}
/**
* Map additional addon routes.
*
* @param Router $router
*/
public function map(Router $router)
{
// Register dynamic routes here for example.
// Use method injection or commands to bring in services.
}
}

View File

@ -0,0 +1,10 @@
.coverage
composer.lock
npm-debug.log
mix-manifest.json
package-lock.json
/bin
/build
/vendor
/coverage
/node_modules

View File

@ -0,0 +1,21 @@
#The MIT License (MIT)
###Copyright (c) 2014 AnomalyLabs, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,7 @@
# Multiple Field Type
*visiosoft.field_type.multiple*
### A multiple relationship field type.
The multiple field type provides a multi-select input for a related model.

View File

@ -0,0 +1,30 @@
{
"name": "visiosoft/multiple-field_type",
"type": "streams-addon",
"description": "A multiple relationship field type.",
"keywords": [
"streams field type",
"streams addon",
"field type"
],
"homepage": "http://pyrocms.com/anomaly/multiple-field_type",
"license": "MIT",
"authors": [
{
"name": "Openclassify, Inc.",
"homepage": "https://openclassify.com/",
"role": "Owner"
}
],
"support": {
"docs": "https://pyrocms.com/documentation/multiple-field-type",
"forum": "https://pyrocms.com/forum/channels/multiple-field-type",
"issues": "https://github.com/pyrocms/pyrocms/issues?q=is:issue is:open [multiple-field-type]",
"source": "https://github.com/anomalylabs/multiple-field-type"
},
"autoload": {
"psr-4": {
"Visiosoft\\MultipleFieldType\\": "src/"
}
}
}

View File

@ -0,0 +1,20 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"choices": "^0.1.0",
"cross-env": "^5.1",
"laravel-mix": "^4.0.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.16.0",
"sass-loader": "^7.1.0"
}
}

View File

@ -0,0 +1,39 @@
<?php
use Visiosoft\MultipleFieldType\Support\Config\RelatedHandler;
return [
'related' => [
'required' => true,
'type' => 'anomaly.field_type.select',
'config' => [
'handler' => RelatedHandler::class,
],
],
'mode' => [
'required' => true,
'type' => 'anomaly.field_type.select',
'config' => [
'options' => [
'tags' => 'visiosoft.field_type.multiple::config.mode.option.tags',
'lookup' => 'visiosoft.field_type.multiple::config.mode.option.lookup',
'checkboxes' => 'visiosoft.field_type.multiple::config.mode.option.checkboxes',
],
],
],
'title_name' => [
'type' => 'anomaly.field_type.text',
],
'min' => [
'type' => 'anomaly.field_type.integer',
'config' => [
'min' => 1,
],
],
'max' => [
'type' => 'anomaly.field_type.integer',
'config' => [
'min' => 1,
],
],
];

View File

@ -0,0 +1,322 @@
/*===============================
= Choices =
===============================*/
.choices {
position: relative;
margin-bottom: 0.5rem;
font-size: 16px;
}
.choices:focus {
outline: none;
}
.choices:last-child {
margin-bottom: 0;
}
.choices.is-disabled .choices__inner, .choices.is-disabled .choices__input {
background-color: #eceeef;
cursor: not-allowed;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.choices.is-disabled .choices__item {
cursor: not-allowed;
}
.choices[data-type*=select-one] {
cursor: pointer;
}
.choices[data-type*=select-one] .choices__inner {
padding-bottom: 7.5px;
}
.choices[data-type*=select-one] .choices__input {
display: block;
width: 100%;
padding: 10px;
border-bottom: 1px solid #DDDDDD;
background-color: #FFFFFF;
margin: 0;
}
.choices[data-type*=select-one] .choices__button {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
padding: 0;
background-size: 8px;
height: 100%;
position: absolute;
top: 50%;
right: 0;
margin-top: -10px;
margin-right: 25px;
height: 20px;
width: 20px;
border-radius: 10em;
opacity: 0.5;
}
.choices[data-type*=select-one] .choices__button:hover, .choices[data-type*=select-one] .choices__button:focus {
opacity: 1;
}
.choices[data-type*=select-one] .choices__button:focus {
box-shadow: 0px 0px 0px 2px #11bef6;
}
.choices[data-type*=select-one]:after {
content: "";
height: 0;
width: 0;
border-style: solid;
border-color: #55595c transparent transparent transparent;
border-width: 5px;
position: absolute;
right: 11.5px;
top: 50%;
margin-top: -2.5px;
pointer-events: none;
}
.choices[data-type*=select-one].is-open:after {
border-color: transparent transparent #55595c transparent;
margin-top: -7.5px;
}
.choices[data-type*=select-one][dir=rtl]:after {
left: 11.5px;
right: auto;
}
.choices[data-type*=select-one][dir=rtl] .choices__button {
right: auto;
left: 0;
margin-left: 25px;
margin-right: 0;
}
.choices[data-type*=select-multiple] .choices__inner, .choices[data-type*=text] .choices__inner {
cursor: text;
}
.choices[data-type*=select-multiple] .choices__button, .choices[data-type*=text] .choices__button {
position: relative;
display: inline-block;
margin-top: 0;
margin-right: -4px;
margin-bottom: 0;
margin-left: 8px;
padding-left: 16px;
border-left: 1px solid #089ccc;
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
background-size: 8px;
width: 8px;
line-height: 1;
opacity: 0.75;
}
.choices[data-type*=select-multiple] .choices__button:hover, .choices[data-type*=select-multiple] .choices__button:focus, .choices[data-type*=text] .choices__button:hover, .choices[data-type*=text] .choices__button:focus {
opacity: 1;
}
.choices__inner {
display: inline-block;
vertical-align: top;
width: 100%;
background-color: #ffffff;
padding: 7.5px 7.5px 3.75px;
border: 1px solid #DDDDDD;
border-radius: 0.1rem;
font-size: 14px;
min-height: 44px;
overflow: hidden;
}
.is-focused .choices__inner, .is-open .choices__inner {
border-color: #b7b7b7;
}
.is-open .choices__inner {
border-radius: 0.1rem 0.1rem 0 0;
}
.is-flipped.is-open .choices__inner {
border-radius: 0 0 0.1rem 0.1rem;
}
.choices__list {
margin: 0;
padding-left: 0;
list-style: none;
}
.choices__list--single {
display: inline-block;
padding: 4px 16px 4px 4px;
width: 100%;
}
[dir=rtl] .choices__list--single {
padding-right: 4px;
padding-left: 16px;
}
.choices__list--single .choices__item {
width: 100%;
}
.choices__list--multiple {
display: inline;
}
.choices__list--multiple .choices__item {
display: inline-block;
vertical-align: middle;
border-radius: 0.1rem;
padding: 4px 10px;
font-size: 12px;
font-weight: 500;
margin-right: 3.75px;
margin-bottom: 3.75px;
background-color: #11bef6;
border: 1px solid #09afe5;
color: #FFFFFF;
word-break: break-all;
}
.choices__list--multiple .choices__item[data-deletable] {
padding-right: 5px;
}
[dir=rtl] .choices__list--multiple .choices__item {
margin-right: 0;
margin-left: 3.75px;
}
.choices__list--multiple .choices__item.is-highlighted {
background-color: #09afe5;
border: 1px solid #089ccc;
}
.is-disabled .choices__list--multiple .choices__item {
background-color: #aaaaaa;
border: 1px solid #919191;
}
.choices__list--dropdown {
display: none;
z-index: 1;
position: absolute;
width: 100%;
background-color: #FFFFFF;
border: 1px solid #DDDDDD;
top: 100%;
margin-top: -1px;
border-bottom-left-radius: 0.1rem;
border-bottom-right-radius: 0.1rem;
overflow: hidden;
word-break: break-all;
}
.choices__list--dropdown.is-active {
display: block;
}
.is-open .choices__list--dropdown {
border-color: #b7b7b7;
}
.is-flipped .choices__list--dropdown {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: -1px;
border-radius: 0.25rem 0.25rem 0 0;
}
.choices__list--dropdown .choices__list {
position: relative;
max-height: 300px;
overflow: auto;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
}
.choices__list--dropdown .choices__item {
position: relative;
padding: 10px;
font-size: 14px;
}
[dir=rtl] .choices__list--dropdown .choices__item {
text-align: right;
}
@media (min-width: 640px) {
.choices__list--dropdown .choices__item--selectable {
padding-right: 100px;
}
.choices__list--dropdown .choices__item--selectable:after {
content: attr(data-select-text);
font-size: 12px;
opacity: 0;
position: absolute;
right: 10px;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
[dir=rtl] .choices__list--dropdown .choices__item--selectable {
text-align: right;
padding-left: 100px;
padding-right: 10px;
}
[dir=rtl] .choices__list--dropdown .choices__item--selectable:after {
right: auto;
left: 10px;
}
}
.choices__list--dropdown .choices__item--selectable.is-highlighted {
background-color: #f2f2f2;
}
.choices__list--dropdown .choices__item--selectable.is-highlighted:after {
opacity: 0.5;
}
.choices__item {
cursor: default;
}
.choices__item--selectable {
cursor: pointer;
}
.choices__item--disabled {
cursor: not-allowed;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: 0.5;
}
.choices__heading {
font-weight: 600;
font-size: 12px;
padding: 10px;
border-bottom: 1px solid #f7f7f7;
color: gray;
}
.choices__button {
text-indent: -9999px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 0;
background-color: transparent;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
}
.choices__button:focus {
outline: none;
}
.choices__input {
display: inline-block;
vertical-align: baseline;
background-color: #ffffff;
font-size: 14px;
margin-bottom: 5px;
border: 0;
border-radius: 0;
max-width: 100%;
padding: 4px 0 4px 2px;
}
.choices__input:focus {
outline: 0;
}
[dir=rtl] .choices__input {
padding-right: 2px;
padding-left: 0;
}
.choices__placeholder {
opacity: 0.5;
}
/*===== End of Choices ======*/

View File

@ -0,0 +1,301 @@
/* Main styles */
.multiple-field_type .selected {
margin-top: calc(15rem / 16);
}
.multiple-field_type .selected table tr td {
padding: 0.5rem;
border-top: none;
border-bottom: none;
}
.multiple-field_type .selected table tr td:first-of-type {
width: 0;
padding-right: calc(15rem / 16);
}
.multiple-field_type .selected table tr td:last-of-type {
padding-left: calc(15rem / 16);
}
/* End main styles */
/* Button */
.multiple-select-btn {
background-color: #6E5DDB;
padding: 1rem 2rem;
font-family: 'Poppins', sans-serif;
font-size: calc(18rem / 16);
border-radius: .25rem;
border: 0;
color: #fff;
display: inline-flex;
align-items: center;
margin-bottom: 2rem;
&:hover {
color: #fff;
}
svg {
width: 1.5rem;
height: auto;
}
}
/* End Button */
/* Modal */
.multiple-select-btn ~ .modal {
.modal-dialog {
@media only screen and (min-width: 576px) {
max-width: calc(840rem / 16);
margin: 1.75rem auto;
}
.modal-content {
.modal-header {
padding: 0;
display: block;
border: 0;
.btn-wrapper {
text-align: right;
button {
margin: 1.5rem 1.5rem .25rem;
padding: 0;
background: none;
border: 0;
svg {
width: 2.25rem;
height: auto;
}
}
}
h4 {
color: #6E5DDB;
padding: 0 1rem;
@media only screen and (min-width: 576px) {
padding: 0 5rem;
}
}
}
.table-filters {
padding: 0 1rem;
margin: 2rem 0;
@media only screen and (min-width: 576px) {
padding: 0 5rem;
}
form {
justify-content: space-between;
select {
border: 0;
box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075);
font-size: calc(14rem / 16);
font-family: 'Poppins', sans-serif;
font-weight: 500;
padding: .5rem 1.5rem;
height: initial;
}
.filter-buttons {
button {
background-color: #6e5ddb;
color: #fff;
}
a {
border-color: #6e5ddb;
color: #6e5ddb;
}
}
}
}
.table-responsive {
padding: 0 1rem;
@media only screen and (min-width: 576px) {
padding: 0 5rem;
}
table {
thead {
tr {
th {
border-bottom: calc(1rem / 16) solid #E5E5E5;
border-top: 0;
font-family: 'Poppins', sans-serif;
font-size: calc(19rem / 16);
font-weight: 600;
color: #505050;
&.buttons {
display: none;
}
a {
color: #505050;
}
}
}
}
tbody {
td {
border-bottom: calc(1rem / 16) solid #E5E5E5;
font-size: calc(19rem / 16);
font-family: 'Poppins', sans-serif;
font-weight: 500;
color: #505050;
&.buttons {
display: none;
}
}
}
tfoot {
th {
border: 0;
padding: 1.35rem 0 !important;
button {
background-color: #6E5DDB;
padding: 1rem 2rem;
font-family: 'Poppins', sans-serif;
font-size: calc(18rem / 16);
border-radius: .25rem;
border: 0;
color: #fff;
display: inline-flex;
align-items: center;
&:focus {
box-shadow: unset;
}
i {
margin-right: .25rem;
}
}
}
td {
padding: .5rem 0;
border: 0;
color: #999;
small {
font-size: calc(15rem / 16);
color: #999 !important;
font-family: 'Poppins', sans-serif;
}
}
}
}
}
}
}
}
/* End Modal */
/* Value table */
.multiple-field_type-value-table {
.table-responsive {
@media only screen and (min-width: 576px) {
padding: 0 4rem;
}
table {
thead {
tr {
th {
border-bottom: calc(1rem / 16) solid #E5E5E5;
border-top: 0;
font-family: 'Poppins', sans-serif;
font-size: calc(19rem / 16);
font-weight: 600;
color: #505050;
a {
color: #505050;
}
}
}
}
tbody {
td {
border-bottom: calc(1rem / 16) solid #E5E5E5;
font-size: calc(19rem / 16);
font-family: 'Poppins', sans-serif;
font-weight: 500;
color: #505050;
&.buttons {
a {
background-color: unset;
border: 0;
color: #DC3545;
font-family: 'Poppins', sans-serif;
font-weight: 500;
display: inline-flex;
align-items: center;
line-height: 1;
font-size: calc(17rem / 16);
cursor: pointer;
}
i {
margin-right: .5rem;
}
}
}
}
tfoot {
th {
border: 0;
padding: 1.35rem 0 !important;
button {
background-color: #6E5DDB;
padding: 1rem 2rem;
font-family: 'Poppins', sans-serif;
font-size: calc(18rem / 16);
border-radius: .25rem;
border: 0;
color: #fff;
display: inline-flex;
align-items: center;
&:focus {
box-shadow: unset;
}
i {
margin-right: .25rem;
}
}
}
td {
padding: .5rem 0;
border: 0;
color: #999;
small {
font-size: calc(15rem / 16);
color: #999 !important;
font-family: 'Poppins', sans-serif;
}
}
}
}
}
}
/* End Value table */

View File

@ -0,0 +1,3 @@
.multiple-field_type .choices {
z-index: 100;
}

View File

@ -0,0 +1,6 @@
<svg id="Group_42321" data-name="Group 42321" xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30">
<g id="Group_15874" data-name="Group 15874">
<path id="Path_10381" data-name="Path 10381" d="M15,0A15,15,0,1,1,0,15,15,15,0,0,1,15,0Z" fill="#f8f8f8"/>
<path id="close" d="M10.557.6l-.6-.6L5.278,4.675.6,0,0,.6,4.675,5.278,0,9.953l.6.6L5.278,5.882l4.675,4.675.6-.6L5.882,5.278Z" transform="translate(9.5 9.5)" fill="#c7c7c7" stroke="#c7c7c7" stroke-linecap="round" stroke-linejoin="round" stroke-width="0.7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 570 B

View File

@ -0,0 +1,12 @@
<svg id="add_5_" data-name="add (5)" xmlns="http://www.w3.org/2000/svg" width="19.96" height="19.96" viewBox="0 0 19.96 19.96">
<g id="Group_16519" data-name="Group 16519">
<g id="Group_16518" data-name="Group 16518">
<path id="Path_10382" data-name="Path 10382" d="M9.98,0a9.98,9.98,0,1,0,9.98,9.98A9.991,9.991,0,0,0,9.98,0Zm0,18.414A8.434,8.434,0,1,1,18.414,9.98,8.444,8.444,0,0,1,9.98,18.414Z" fill="#fff"/>
</g>
</g>
<g id="Group_16521" data-name="Group 16521" transform="translate(5.342 5.272)">
<g id="Group_16520" data-name="Group 16520">
<path id="Path_10383" data-name="Path 10383" d="M145.526,139.1h-3.092v-3.092a.773.773,0,0,0-1.546,0V139.1H137.8a.773.773,0,0,0,0,1.546h3.092v3.092a.773.773,0,0,0,1.546,0v-3.092h3.092a.773.773,0,1,0,0-1.546Z" transform="translate(-137.022 -135.238)" fill="#fff"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 898 B

View File

@ -0,0 +1,75 @@
/**
* Prompts the user for multiple choice
*
* `choices` are displayed in an ordered list, user is prompted with message,
* callback is returned with the index of the choice.
*
* @param prompt String Message to show users
* @param choices Array[String] Names of the choices
* @param callback Function Callback the function when a valid choice is made
*
* @install
* npm install choices
*
* @example
*
* var choices = require('choices');
* var options = ['First Option', 'Second option', 'Third option'];
* choices('Pick an option', options, function(idx) {
* console.log('You picked ' + options[idx]);
* });
*
* [1]: First option
* [2]: Second option
* [3]: Third option
* Pick an option>> 2
* You picked Second option
*
* @todo Add support for more than 9 options (key number + enter)
*
*/
var Choices = module.exports = function Choices(prompt, options, callback) {
var stdin = process.stdin;
var colors = require('colors');
if (options.length > 9) {
throw new Error('choices only supports < 9 choices');
}
options.forEach(function(name, idx) {
console.log(' ['.bold + ('' + (idx + 1)).green.bold + ']'.bold + ': ' + name);
});
process.stdout.write(prompt + '>> '.red);
stdin.setRawMode(true);
stdin.resume();
stdin.once(
'data',
function(key) {
var idx,
charCode = key.toString('utf8').charCodeAt(0);
stdin.pause();
stdin.setRawMode(false);
var re = /[\0-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g;
process.stdout.write(key.toString('utf8').replace(re, '') + "\n");
if (charCode == 3 || charCode == 27 || charCode == 113 || charCode == 81) {
return callback(null);
}
idx = +key;
if (idx > 0 && idx <= options.length)
return callback(idx - 1);
process.nextTick(function() {
Choices(prompt, options, callback);
});
}
);
};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,90 @@
$(document).on('ajaxComplete ready', function () {
// Initialize multiple pickers
$('input[data-provides="visiosoft.field_type.multiple"]:not([data-initialized])').each(function () {
$(this).attr('data-initialized', '');
let input = $(this);
let field = input.data('field_name');
let wrapper = input.closest('.form-group');
let modal = $('#' + field + '-modal');
let selected = $('[name="' + field + '"]').val().split(',');
modal.on('click', '[data-entry]', function (e) {
e.preventDefault();
selected.push(String($(this).data('entry')));
$('[name="' + field + '"]').val($.unique(selected).join(','));
$(this).closest('tr').addClass('success').fadeOut();
wrapper.find('.selected').load(REQUEST_ROOT_PATH + '/streams/multiple-field_type/selected/' + $(this).data('key') + '?uploaded=' + selected.join(','), function () {
wrapper.sort();
});
$(wrapper).find('[data-dismiss="multiple"]').removeClass('hidden');
});
modal.on('click', '[name="action"][value="add_selected"]', function(e) {
e.preventDefault();
$('input[type="checkbox"][data-toggle="action"]:checked').each(function () {
selected.push(String($(this).val()));
$(this).closest('tr').addClass('success').fadeOut();
});
$('[name="' + field + '"]').val(selected.join(','));
wrapper.find('.selected').load(
REQUEST_ROOT_PATH + '/streams/multiple-field_type/selected/' + $(this).data('key') + '?uploaded=' + selected.join(','),
function() {
wrapper.sort();
}
);
});
$(wrapper).on('click', '[data-dismiss="multiple"]', function (e) {
e.preventDefault();
selected.splice(selected.indexOf(String($(this).data('entry'))), 1);
$('[name="' + field + '"]').val(selected.join(','));
$(this).closest('tr').addClass('danger').fadeOut();
});
wrapper.sort = function () {
wrapper.find('.selected table').sortable({
nested: false,
handle: '.handle',
itemSelector: 'tr',
itemPath: '> tbody',
containerSelector: 'table',
placeholder: '<tr class="placeholder"/>',
afterMove: function ($placeholder) {
$placeholder.closest('table').find('button.reorder').removeClass('disabled');
$placeholder.closest('table').find('.dragged').detach().insertBefore($placeholder);
selected = [];
$(wrapper.find('table').find('[data-dismiss="multiple"]')).each(function () {
selected.push(String($(this).data('entry')));
});
$('[name="' + field + '"]').val(selected.join(','));
}
});
}
// Sort initially
wrapper.sort();
});
});

View File

@ -0,0 +1,13 @@
(function (window, document) {
let fields = Array.prototype.slice.call(
document.querySelectorAll('select[data-provides="visiosoft.field_type.multiple"]')
);
fields.forEach(function (field) {
new Choices(field, {
removeItemButton: true,
searchResultLimit: 10,
});
});
})(window, document);

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'متعدد',
'name' => 'نوع الحقل المتعدد',
'description' => 'نوع الحقل النتعدد العلاقات.',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'الدفق المرتبط',
'instructions' => 'حدد إدخالات الدفق ذات الصلة لعرضها ضمن القائمة المنسدلة.',
],
'mode' => [
'label' => 'وضخ الإدخال',
'option' => [
'tags' => 'الأوسمة',
'lookup' => 'ابحث عن',
'checkboxes' => 'مربعات الاختيار',
],
],
'min' => [
'label' => 'الحد الأدنى للاختيارات',
'instructions' => 'حدد الحد الأدني للاختيارات المسموحة.',
],
'max' => [
'label' => 'الحد الأعلى للاختيارات',
'instructions' => 'حدد عدد الحد الأعلى اللاختيارات المسموحة.',
],
'title_name' => [
'label' => 'حقل العنوان',
'placeholder' => 'الاسم الأول',
'instructions' => 'حدد <strong>slug</strong> لعرضه لخيارات القائمة المنسدلة / البحث.<br>يمكنك تحديد عناوين قابلة للتحليل مثل <strong>{entry.first_name} {entry.last_name}</strong><br>سيتم استخدام عمود عنوان التدفق ذي الصلة افتراضيًا.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'اختر خيار...',
'help' => 'اختر القيم بحيث يكون بينها فاصلة , ثم اضغط "ادخال".',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'حدد الإدخالات التي تريد اضافتها.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'Mehrfachbeziehungen',
'name' => 'Mehrfachbeziehungen Feldtyp',
'description' => 'Ein Feldtyp für Mehrfachbeziehungen.',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'Verbundener Stream',
'instructions' => 'Geben Sie den verbunden Stream an, dessen Einträge im Dropdown zur Auswahl stehen sollen.',
],
'mode' => [
'label' => 'Eingabemodus',
'option' => [
'tags' => 'Stichworte',
'lookup' => 'Nachschlagen',
'checkboxes' => 'Kontrollkästchen',
],
],
'min' => [
'label' => 'Minimalauswahl',
'instructions' => 'Geben Sie die minimale Anzahl an auszuwählenden Einträgen ein.',
],
'max' => [
'label' => 'Maximalauswahl',
'instructions' => 'Geben Sie die maximal erlaubte Anzahl an ausgewählten Einträgen an.',
],
'title_name' => [
'label' => 'Titelfeld',
'placeholder' => 'Vorname',
'instructions' => 'Geben Sie den <strong>Slug</strong> des Felds an, das für Dropdown- / Suchoptionen angezeigt werden soll.<br>Sie können analysierbare Titel wie <strong>{entry.first_name} {entry.last_name}</strong><br>angeben. Die Titelspalte des zugehörigen Streams wird standardmäßig verwendet.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'Wählen Sie eine Option...',
'help' => 'Trennen Sie Ihre Eingaben mit einem Komma oder durch drücken der Taste Enter.',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'Wählen Sie die Einträge aus, die Sie hinzufügen möchten.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'Multiple',
'name' => 'Multiple Field Type',
'description' => 'A multiple relationship field type.',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'Related Stream',
'instructions' => 'Specify the related stream entries to display in the dropdown.',
],
'mode' => [
'label' => 'Input Mode',
'option' => [
'tags' => 'Tags',
'lookup' => 'Lookup',
'checkboxes' => 'Checkboxes',
],
],
'min' => [
'label' => 'Minimum Selections',
'instructions' => 'Specify the minimum number of allowed selections.',
],
'max' => [
'label' => 'Maximum Selections',
'instructions' => 'Specify the maximum number of allowed selections.',
],
'title_name' => [
'label' => 'Title Field',
'placeholder' => 'first_name',
'instructions' => 'Specify the <strong>slug</strong> of field to display for dropdown/search options.<br>You can specify parsable titles like <strong>{entry.first_name} {entry.last_name}</strong><br>The related stream\'s title column will be used by default.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'Choose an option...',
'help' => 'Separate values with a comma or by pressing "Enter".',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'Select the entries you would like to add.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'Plusieurs',
'name' => 'Multiple',
'description' => 'Type de champs pour les relations multiples.',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'Stream en relation',
'instructions' => 'Choisissez les entrées à afficher dans la sélection.',
],
'mode' => [
'label' => 'Mode d\'entrée',
'option' => [
'tags' => 'Mots clés',
'lookup' => 'Chercher',
'checkboxes' => 'Cases à cocher',
],
],
'min' => [
'label' => 'Nombre de sélection minimum',
'instructions' => 'Entrez un nombre minimum de sélection.',
],
'max' => [
'label' => 'Nombre de sélection maximum',
'instructions' => 'Entrez un nombre maximum de sélection.',
],
'title_name' => [
'label' => 'Champ de titre',
'placeholder' => 'Prénom',
'instructions' => 'Spécifiez le <strong>slug</strong> du champ à afficher pour les options de liste déroulante / de recherche.<br>Vous pouvez spécifier des titres analysables tels que <strong>{entry.first_name} {entry.last_name}</strong><br>La colonne de titre du flux associé sera utilisée par défaut.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'Choisissez une option...',
'help' => 'Séparez les valeurs par une virgule ou en tapant "Entrée".',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'Sélectionnez les entrées que vous souhaitez ajouter.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'Többszörös',
'name' => 'Többszörös Mező Típus',
'description' => 'Többszörös kapcsolat mező típus.',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'Releváns Folyam',
'instructions' => 'Határozd meg a releváns folyamat a legördülő megjelenítéséhez.',
],
'mode' => [
'label' => 'Bevitel Módja',
'option' => [
'tags' => 'Cimkék',
'lookup' => 'Átvizsgálás',
'checkboxes' => 'Jelölőnégyzetek',
],
],
'min' => [
'label' => 'Minimális Kiválasztás',
'instructions' => 'Határozd meg a minimálisan kiválasztható elemek számát.',
],
'max' => [
'label' => 'Maximális Kiválasztás',
'instructions' => 'Határozd meg a maximálisan kiválasztható elemek számát.',
],
'title_name' => [
'label' => 'Cím mező',
'placeholder' => 'keresztnév',
'instructions' => 'Adja meg a <strong></strong> mezõjét a megjelenítendõ legördülõ / keresési opciókhoz.<br>Megadhat értelmezhető címeket, például <strong>{entry.first_name} {entry.last_name}</strong><br>Alapértelmezés szerint a kapcsolódó adatfolyam oszlopát fogja használni.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'Válassz elemet...',
'help' => 'Az értékeket szóközzel, vagy enterrel válaszd el.',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'Válaszd ki a bejegyzéseket amiket hozzá szeretnél adni.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => 'Çoklu',
'name' => 'Çoklu Alan Tipi',
'description' => 'Bir çoklu ilişki alan tipi',
];

View File

@ -0,0 +1,29 @@
<?php
return [
'related' => [
'label' => 'İlişkili Stream',
'instructions' => 'Açılırlistede gösterilecek ilişkili stream girişlerini belirtin.',
],
'mode' => [
'label' => 'Giriş Modu',
'option' => [
'tags' => 'Etiketler',
'lookup' => 'Bakış',
'checkboxes' => 'Onay Kutuları',
],
],
'min' => [
'label' => 'Minimum seçim sayısı',
'instructions' => 'İzin verilen minimum seçim sayısını belirtin.',
],
'max' => [
'label' => 'Maksimum seçim sayısı',
'instructions' => 'İzin verilen maksimum seçim sayısını belirtin.',
],
'title_name' => [
'label' => 'Başlık Alanı',
'placeholder' => 'İsim',
'instructions' => 'Açılır menü / arama seçeneklerini görüntülemek için alanın <strong>slug</strong> değerini belirtin.<br> <strong>{entry.first_name} {entry.last_name}</strong><br> gibi sütun isimleri belirtebilirsiniz.',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => 'Bir seçim yapın...',
'help' => 'Girişleri, arasına virgül koyarak veya "Enter" tuşuna basarak ayırabilirsiniz.',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => 'Eklemek istediğiniz girişleri seçin.',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => '多个',
'name' => '多个字段类型',
'description' => '一个多个关系字段类型。',
];

View File

@ -0,0 +1,23 @@
<?php
return [
'related' => [
'label' => '关系表',
'instructions' => '指定在下拉框中数据所属的关系表。',
],
'mode' => [
'label' => '输入类型',
'option' => [
'tags' => '标签',
'lookup' => '查找',
],
],
'min' => [
'label' => '最少选项数',
'instructions' => '指定允许最小的选项数量。',
],
'max' => [
'label' => '最多选项数',
'instructions' => '指定允许最多的选项数量。',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => '请选择一个选项',
'help' => '请使用逗号或者回车键来分开不同选项。',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => '选择你想添加的具体实例。',
];

View File

@ -0,0 +1,7 @@
<?php
return [
'title' => '多重',
'name' => '多重欄位型別',
'description' => '一個具有多重關係的欄位型別。',
];

View File

@ -0,0 +1,23 @@
<?php
return [
'related' => [
'label' => '關連的資料流',
'instructions' => '指定在下拉選單中資料所屬的資料流。',
],
'mode' => [
'label' => '輸入模式',
'option' => [
'tags' => '標籤',
'lookup' => '查找',
],
],
'min' => [
'label' => '最小選項數量',
'instructions' => '指定允許的最小選項數量。',
],
'max' => [
'label' => '最大選項數量',
'instructions' => '指定允許的最大選項數量。',
],
];

View File

@ -0,0 +1,6 @@
<?php
return [
'placeholder' => '請選擇一個項目...',
'help' => '請使用英文逗號或換行來區別不同的項目。',
];

View File

@ -0,0 +1,5 @@
<?php
return [
'select_entries' => '選擇您想新增的項目。',
];

View File

@ -0,0 +1,340 @@
/*===============================
= Choices =
===============================*/
$choices-selector: 'choices' !default;
$choices-font-size-lg: 16px !default;
$choices-font-size-md: 14px !default;
$choices-font-size-sm: 12px !default;
$choices-guttering: 0.5rem !default;
$choices-border-radius: .1rem !default;
$choices-border-radius-item: .1rem !default;
$choices-bg-color: #ffffff !default;
$choices-bg-color-disabled: #eceeef !default;
$choices-bg-color-dropdown: #FFFFFF !default;
$choices-text-color: #55595c !default;
$choices-keyline-color: #DDDDDD !default;
$choices-primary-color: #11bef6 !default;
$choices-disabled-color: #eaeaea !default;
$choices-highlight-color: $choices-primary-color !default;
$choices-button-icon-path: '../../icons' !default;
$choices-button-dimension: 8px !default;
$choices-button-offset: 8px !default;
.#{$choices-selector} {
position: relative;
margin-bottom: $choices-guttering;
font-size: $choices-font-size-lg;
&:focus {
outline: none;
}
&:last-child {
margin-bottom: 0;
}
&.is-disabled {
.#{$choices-selector}__inner, .#{$choices-selector}__input {
background-color: $choices-bg-color-disabled;
cursor: not-allowed;
user-select: none;
}
.#{$choices-selector}__item {
cursor: not-allowed;
}
}
}
.#{$choices-selector}[data-type*="select-one"] {
cursor: pointer;
.#{$choices-selector}__inner {
padding-bottom: 7.5px;
}
.#{$choices-selector}__input {
display: block;
width: 100%;
padding: 10px;
border-bottom: 1px solid $choices-keyline-color;
background-color: #FFFFFF;
margin: 0;
}
.#{$choices-selector}__button {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
padding: 0;
background-size: 8px;
height: 100%;
position: absolute;
top: 50%;
right: 0;
margin-top: -10px;
margin-right: 25px;
height: 20px;
width: 20px;
border-radius: 10em;
opacity: .5;
&:hover, &:focus {
opacity: 1;
}
&:focus {
box-shadow: 0px 0px 0px 2px $choices-highlight-color;
}
}
&:after {
content: "";
height: 0;
width: 0;
border-style: solid;
border-color: $choices-text-color transparent transparent transparent;
border-width: 5px;
position: absolute;
right: 11.5px;
top: 50%;
margin-top: -2.5px;
pointer-events: none;
}
&.is-open:after {
border-color: transparent transparent $choices-text-color transparent;
margin-top: -7.5px;
}
&[dir="rtl"] {
&:after {
left: 11.5px;
right: auto;
}
.#{$choices-selector}__button {
right: auto;
left: 0;
margin-left: 25px;
margin-right: 0;
}
}
}
.#{$choices-selector}[data-type*="select-multiple"], .#{$choices-selector}[data-type*="text"] {
.#{$choices-selector}__inner {
cursor: text;
}
.#{$choices-selector}__button {
position: relative;
display: inline-block;
margin-top: 0;
margin-right: -$choices-button-offset/2;
margin-bottom: 0;
margin-left: $choices-button-offset;
padding-left: $choices-button-offset*2;
border-left: 1px solid darken($choices-primary-color, 10%);
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
background-size: $choices-button-dimension;
width: $choices-button-dimension;
line-height: 1;
opacity: .75;
&:hover, &:focus {
opacity: 1;
}
}
}
.#{$choices-selector}__inner {
display: inline-block;
vertical-align: top;
width: 100%;
background-color: $choices-bg-color;
padding: 7.5px 7.5px 3.75px;
border: 1px solid $choices-keyline-color;
border-radius: $choices-border-radius;
font-size: $choices-font-size-md;
min-height: 44px;
overflow: hidden;
.is-focused &, .is-open & {
border-color: darken($choices-keyline-color, 15%);
}
.is-open & {
border-radius: $choices-border-radius $choices-border-radius 0 0;
}
.is-flipped.is-open & {
border-radius: 0 0 $choices-border-radius $choices-border-radius;
}
}
.#{$choices-selector}__list {
margin: 0;
padding-left: 0;
list-style: none;
}
.#{$choices-selector}__list--single {
display: inline-block;
padding: 4px 16px 4px 4px;
width: 100%;
[dir="rtl"] & {
padding-right: 4px;
padding-left: 16px;
}
.#{$choices-selector}__item {
width: 100%;
}
}
.#{$choices-selector}__list--multiple {
display: inline;
.#{$choices-selector}__item {
display: inline-block;
vertical-align: middle;
border-radius: $choices-border-radius-item;
padding: 4px 10px;
font-size: $choices-font-size-sm;
font-weight: 500;
margin-right: 3.75px;
margin-bottom: 3.75px;
background-color: $choices-primary-color;
border: 1px solid darken($choices-primary-color, 5%);
color: #FFFFFF;
word-break: break-all;
&[data-deletable] {
padding-right: 5px;
}
[dir="rtl"] & {
margin-right: 0;
margin-left: 3.75px;
}
&.is-highlighted {
background-color: darken($choices-primary-color, 5%);
border: 1px solid darken($choices-primary-color, 10%);
}
.is-disabled & {
background-color: darken($choices-disabled-color, 25%);
border: 1px solid darken($choices-disabled-color, 35%);
}
}
}
.#{$choices-selector}__list--dropdown {
display: none;
z-index: 1;
position: absolute;
width: 100%;
background-color: $choices-bg-color-dropdown;
border: 1px solid $choices-keyline-color;
top: 100%;
margin-top: -1px;
border-bottom-left-radius: $choices-border-radius;
border-bottom-right-radius: $choices-border-radius;
overflow: hidden;
word-break: break-all;
&.is-active {
display: block;
}
.is-open & {
border-color: darken($choices-keyline-color, 15%);
}
.is-flipped & {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: -1px;
border-radius: .25rem .25rem 0 0;
}
.#{$choices-selector}__list {
position: relative;
max-height: 300px;
overflow: auto;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
}
.#{$choices-selector}__item {
position: relative;
padding: 10px;
font-size: $choices-font-size-md;
[dir="rtl"] & {
text-align: right;
}
}
.#{$choices-selector}__item--selectable {
@media (min-width: 640px) {
padding-right: 100px;
&:after {
content: attr(data-select-text);
font-size: $choices-font-size-sm;
opacity: 0;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
[dir="rtl"] & {
text-align: right;
padding-left: 100px;
padding-right: 10px;
&:after {
right: auto;
left: 10px;
}
}
}
&.is-highlighted {
background-color: mix(#000000, #FFFFFF, 5%);
&:after {
opacity: .5;
}
}
}
}
.#{$choices-selector}__item {
cursor: default;
}
.#{$choices-selector}__item--selectable {
cursor: pointer;
}
.#{$choices-selector}__item--disabled {
cursor: not-allowed;
user-select: none;
opacity: .5;
}
.#{$choices-selector}__heading {
font-weight: 600;
font-size: $choices-font-size-sm;
padding: 10px;
border-bottom: 1px solid lighten($choices-keyline-color, 10%);
color: lighten(#333, 30%);
}
.#{$choices-selector}__button {
text-indent: -9999px;
-webkit-appearance: none;
appearance: none;
border: 0;
background-color: transparent;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
&:focus {
outline: none;
}
}
.#{$choices-selector}__input {
display: inline-block;
vertical-align: baseline;
background-color: $choices-bg-color;
font-size: $choices-font-size-md;
margin-bottom: 5px;
border: 0;
border-radius: 0;
max-width: 100%;
padding: 4px 0 4px 2px;
&:focus {
outline: 0;
}
[dir="rtl"] & {
padding-right: 2px;
padding-left: 0;
}
}
.#{$choices-selector}__placeholder {
opacity: .5;
}
/*===== End of Choices ======*/

View File

@ -0,0 +1,21 @@
.multiple-field_type {
.selected {
margin-top: 15px;
table tr td {
padding: 0.5rem;
border-top: none;
border-bottom: none;
&:first-of-type {
width: 0;
padding-right: 15px;
}
&:last-of-type {
padding-left: 15px;
}
}
}
}

View File

@ -0,0 +1,5 @@
.multiple-field_type {
.choices {
z-index: 100;
}
}

View File

@ -0,0 +1,41 @@
<div class="custom-inputs-stacked">
{% for key, title in field_type.options %}
{% if title is iterable %}
<p>
<strong> {{ trans(key) }} </strong>
{% for key, title in title %}
<label class="custom-checkbox" style="display: block;">
<input
type="checkbox"
value="{{ key }}"
name="{{ field_type.input_name }}[]"
{{ field_type.disabled ? 'disabled' }}
{{ key in field_type.config.disabled ? 'disabled' }}
{{ key in field_type.config.checked ? 'checked' }}
{{ key in field_type.ids ? 'checked' }}>
{{ trans(title)|raw }}
</label>
{% endfor %}
</p>
{% else %}
<label class="custom-checkbox" style="display: block;">
<input
type="checkbox"
value="{{ key }}"
name="{{ field_type.input_name }}[]"
{{ field_type.disabled ? 'disabled' }}
{{ key in field_type.config.disabled ? 'disabled' }}
{{ key in field_type.config.checked ? 'checked' }}
{{ key in field_type.ids ? 'checked' }}>
{{ trans(title)|raw }}
</label>
{% endif %}
{% endfor %}
</div>

View File

@ -0,0 +1,11 @@
<select
class="custom-select form-control"
name="{{ field_type.input_name }}">
<option value="" disabled {{ not field_type.value ? 'selected' }}>{{ trans(field_type.placeholder) }}</option>
{% for value, option in field_type.options %}
<option value="{{ value }}" {{ value == field_type.value ? 'selected' }}>{{ trans(option) }}</option>
{% endfor %}
</select>

View File

@ -0,0 +1,24 @@
{{ asset_add('styles.css', 'visiosoft.field_type.multiple::css/lookup.scss') }}
{{ asset_add('scripts.js', 'visiosoft.field_type.multiple::js/lookup.js') }}
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<a data-toggle="modal" data-target="#{{ field_type.field_name }}-modal"
class="multiple-select-btn"
href="{{ url('streams/multiple-field_type/index/' ~ field_type.key) }}">
{{ img('visiosoft.field_type.multiple::images/plus.svg').data|raw }}
<span class="ml-1">{{ trans('streams::button.select') }}</span>
</a>
<input type="hidden" name="{{ field_type.input_name }}" value="{{ field_type.ids('id')|join(',') }}" {{ html_attributes(field_type.attributes) }} {{ field_type.disabled ? 'disabled' }} {{ field_type.readonly ? 'readonly' }}>
<div class="selected">
{{ field_type.table|raw }}
</div>
<div class="modal remote" id="{{ field_type.field_name }}-modal">
<div class="modal-dialog modal-wide">
<div class="modal-content"></div>
</div>
</div>

View File

@ -0,0 +1,53 @@
{{ asset_add("scripts.js", "streams::js/table/table.js") }}
{% if not actions.isEmpty() %}
{{ asset_add("scripts.js", "streams::js/table/actions.js") }}
{% endif %}
{% if table.options.sortable %}
{{ asset_add("scripts.js", "streams::js/table/sortable.js") }}
{% endif %}
{{ view("visiosoft.field_type.multiple::table/ajax/heading", {'table': table}) }}
{{ view("visiosoft.field_type.multiple::table/ajax/views", {'table': table}) }}
{{ view("visiosoft.field_type.multiple::table/ajax/filters", {'table': table}) }}
{% if table.rows.isEmpty() %}
{% block no_results %}
<div class="no-results">
<p>
{{ trans(table.options.get('no_results_message', 'streams::message.no_results')) }}
</p>
</div>
{% endblock %}
{% endif %}
{% if not table.rows.isEmpty() %}
{{ form_open({'url': url_full(), 'class': 'ajax'}) }}
<div class="table-responsive">
<table
class="
table ajax table--ajax
{{ table.options.class ?: 'table-condensed table--condensed' }}
{{ table.options.sortable ? 'table--sortable' }}
"
{{ table.options.sortable ? 'data-sortable' }}
{{ html_attributes(table.options.attributes) }}>
{{ view("visiosoft.field_type.multiple::table/ajax/header", {'table': table}) }}
{% block body %}
{{ view("visiosoft.field_type.multiple::table/partials/body", {'table': table}) }}
{% endblock %}
{{ view("streams::table/partials/footer", {'table': table}) }}
</table>
</div>
{{ form_close() }}
{% endif %}

View File

@ -0,0 +1,27 @@
{% if not table.filters.isEmpty() %}
<div class="table-filters">
{{ form_open({'method': 'get', 'id': 'filters', 'url': url_full(), 'class': 'ajax form-inline'}) }}
<input type="hidden" name="{{ table.options.prefix }}view" value="{{ table.views.active().getSlug() }}">
<input type="hidden" name="{{ table.options.prefix }}page" value="">
{% for filter in table.filters %}
<div class="form-group mb-0">
{{ filter.input|raw }}
</div>
{% endfor %}
<div class="filter-buttons">
<button type="submit" class="btn">
{{ icon(table.options.filters.filter_icon ?: 'filter') }}
{{ trans(table.options.filters.filter_text ?: 'streams::button.filter') }}
</button>
<a href="{{ url_current() }}" class="btn ajax">
{{ icon(table.options.filters.clear_icon ? table.options.filters.clear_icon) }}
{{ trans(table.options.filters.clear_text ?: 'streams::button.clear') }}
</a>
</div>
{{ form_close() }}
</div>
{% endif %}

View File

@ -0,0 +1,36 @@
<thead>
<tr>
{% if table.options.sortable %}
<th style="width: 30px;">&nbsp;</th>
{% endif %}
{% if not table.actions.isEmpty() %}
<th style="width: 30px;">
<input data-toggle="all" type="checkbox">
</th>
{% endif %}
{% for header in table.headers %}
<th>
{% if header.sortable %}
{{ html_link(url_current() ~ '?' ~ header.getQueryString(), trans(header.heading), {'class': 'ajax'}) }}
{% if header.direction == 'asc' %}
{{ icon('sort-ascending', 'text-muted') }}
{% elseif header.direction == 'desc' %}
{{ icon('sort-descending', 'text-muted') }}
{% else %}
{{ icon('sortable', 'text-muted') }}
{% endif %}
{% else %}
{{ trans(header.heading)|raw }}
{% endif %}
</th>
{% endfor %}
<th class="buttons">&nbsp;</th>
</tr>
</thead>

View File

@ -0,0 +1,19 @@
{% if (table.options.title or table.options.description) and table.options.title %}
<div class="modal-header">
<div class="btn-wrapper">
<button data-dismiss="modal">
{{ img('visiosoft.field_type.multiple::images/close.svg').data|raw }}
</button>
</div>
<h4 class="modal-title">
{{ trans(table.options.title)|raw }}
{% if table.options.description %}
<small class="clearfix">
{{ trans(table.options.description)|raw }}
</small>
{% endif %}
</h4>
</div>
{% endif %}

View File

@ -0,0 +1,14 @@
{% if not table.views.isEmpty() %}
<nav class="navbar navbar-light">
<div class="nav navbar-nav">
{% for view in table.views %}
<a
class="ajax nav-item nav-link {{ view.class }} {{ view.isActive() ? 'active' }}"
{{ html_attributes(view.attributes) }}>
{{ view.icon ? icon(view.icon)|raw }}
{{ trans(view.getText()) }}
</a>
{% endfor %}
</div>
</nav>
{% endif %}

View File

@ -0,0 +1,31 @@
<tbody>
{% for row in table.rows %}
<tr id="{{ loop.index }}" class="{{ row.class }}">
{% if table.options.sortable %}
<td>
{{ icon('fa fa-arrows handle') }}
<input type="hidden" name="{{ row.table.options.prefix }}order[]" value="{{ row.key }}"/>
</td>
{% endif %}
{% if not table.actions.isEmpty() %}
<td>
<input type="checkbox" data-toggle="action" name="{{ row.table.options.prefix }}id[]" value="{{ row.key }}"/>
</td>
{% endif %}
{% for column in row.columns %}
<td data-title="{{ trans(column.heading) }}"
class="{{ column.class }}" {{ html_attributes(column.attributes) }}>
{{ column.value|raw }}
</td>
{% endfor %}
<td class="text-lg-right buttons">
<nobr>{{ buttons(row.buttons)|raw }}</nobr>
</td>
</tr>
{% endfor %}
</tbody>

View File

@ -0,0 +1,34 @@
{{ asset_add("scripts.js", "streams::js/table/jquery-sortable.js") }}
{% if not table.rows.isEmpty() %}
{% block panel %}
<div class="{{ table.options.panel_class }} panel-table multiple-field_type-value-table">
<div class="table-responsive">
<table
class="{{ table.options.class ?: 'table' }}"
{{ table.options.sortable ? 'data-sortable' }}
{{ html_attributes(table.options.attributes) }}>
{{ view("visiosoft.field_type.multiple::table/ajax/header", {'table': table}) }}
{% block body %}
{{ view("visiosoft.field_type.multiple::table/partials/body", {'table': table}) }}
{% endblock %}
</table>
</div>
</div>
{% endblock %}
{% else %}
{% block no_results %}
<div class="{{ table.options.panel_class }}">
<div class="{{ table.options.panel_body_class }}">
{{ trans(table.options.get('no_results_message', 'streams::message.no_results')) }}
</div>
</div>
{% endblock %}
{% endif %}

View File

@ -0,0 +1,22 @@
{{ asset_add("styles.css", "visiosoft.field_type.multiple::css/choices.css", ["as:jshjohnson/Choices.css"]) }}
{{ asset_add("scripts.js", "visiosoft.field_type.multiple::js/choices.min.js", ["as:jshjohnson/Choices.js"]) }}
{{ asset_add("styles.css", "visiosoft.field_type.multiple::css/tags.css") }}
{{ asset_add("scripts.js", "visiosoft.field_type.multiple::js/tags.js") }}
<select multiple
data-key="{{ field_type.key }}"
name="{{ field_type.input_name }}[]"
data-placeholder="{{ trans(field_type.placeholder) }}"
{{ html_attributes(field_type.attributes) }}
{{ field_type.disabled ? 'disabled' }}
{{ field_type.readonly ? 'readonly' }}>
{% for key, title in field_type.options %}
<option {{ key in field_type.ids ? 'selected' }} value="{{ key }}">{{ title }}</option>
{% endfor %}
</select>
<small class="text-muted">
{{ trans('visiosoft.field_type.multiple::input.help') }}
</small>

View File

@ -0,0 +1,53 @@
<?php namespace Visiosoft\MultipleFieldType\Command;
use Visiosoft\MultipleFieldType\MultipleFieldType;
use Illuminate\Container\Container;
class BuildOptions
{
/**
* The field type instance.
*
* @var MultipleFieldType
*/
protected $fieldType;
/**
* Create a new BuildOptions instance.
*
* @param MultipleFieldType $fieldType
*/
function __construct(MultipleFieldType $fieldType)
{
$this->fieldType = $fieldType;
}
/**
* Handle the command.
*
* @param Container $container
*/
public function handle(Container $container)
{
if ($options = $this->fieldType->config('options')) {
$this->fieldType->setOptions($options);
return;
}
$model = $this->fieldType->getRelatedModel();
$handler = $this->fieldType->config('handler', $model->getMultipleFieldTypeOptionsHandler());
if (!class_exists($handler) && !str_contains($handler, '@')) {
$handler = array_get($this->fieldType->getHandlers(), $handler);
}
if (is_string($handler) && !str_contains($handler, '@')) {
$handler .= '@handle';
}
$container->call($handler, ['fieldType' => $this->fieldType]);
}
}

View File

@ -0,0 +1,39 @@
<?php namespace Visiosoft\MultipleFieldType\Command;
use Anomaly\Streams\Platform\Support\Collection;
use Illuminate\Contracts\Cache\Repository;
use Illuminate\Support\Facades\Crypt;
class GetConfiguration
{
/**
* The config key.
*
* @var string
*/
protected $key;
/**
* Create a new GetConfiguration instance.
*
* @param string $key
*/
public function __construct($key)
{
$this->key = $key;
}
/**
* Handle the command.
*
* @param Repository $cache
* @return Collection
*/
public function handle(Repository $cache)
{
return new Collection(
array_merge(Crypt::decrypt($this->key), ['key' => $this->key])
);
}
}

View File

@ -0,0 +1,65 @@
<?php namespace Visiosoft\MultipleFieldType\Handler;
use Visiosoft\MultipleFieldType\MultipleFieldType;
use Anomaly\Streams\Platform\Support\Value;
class Related
{
/**
* Handle the options.
*
* @param MultipleFieldType $fieldType
* @param Value $value
* @return array
*/
public function handle(MultipleFieldType $fieldType, Value $value)
{
$model = $fieldType->getRelatedModel();
$query = $model->newQuery();
$results = $query->get();
try {
/**
* Try and use a non-parsing pattern.
*/
if (strpos($fieldType->config('title_name', $model->getTitleName()), '{') === false) {
$fieldType->setOptions(
$results->pluck(
$fieldType->config('title_name', $model->getTitleName()),
$fieldType->config('key_name', $model->getKeyName())
)->all()
);
}
/**
* Try and use a parsing pattern.
*/
if (strpos($fieldType->config('title_name', $model->getTitleName()), '{') !== false) {
$fieldType->setOptions(
array_combine(
$results->map(
function ($item) use ($fieldType, $model) {
return data_get($item, $fieldType->config('key_name', $model->getKeyName()));
}
)->all(),
$results->map(
function ($item) use ($fieldType, $model, $value) {
return $value->make($fieldType->config('title_name', $model->getTitleName()), $item);
}
)->all()
)
);
}
} catch (\Exception $e) {
$fieldType->setOptions(
$results->pluck(
$model->getTitleName(),
$model->getKeyName()
)->all()
);
}
}
}

View File

@ -0,0 +1,106 @@
<?php namespace Visiosoft\MultipleFieldType\Http\Controller;
use Visiosoft\MultipleFieldType\Command\GetConfiguration;
use Visiosoft\MultipleFieldType\MultipleFieldType;
use Visiosoft\MultipleFieldType\Table\LookupTableBuilder;
use Visiosoft\MultipleFieldType\Table\SelectedTableBuilder;
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
use Anomaly\Streams\Platform\Http\Controller\AdminController;
use Anomaly\Streams\Platform\Model\EloquentModel;
use Anomaly\Streams\Platform\Support\Collection;
use Illuminate\Contracts\Container\Container;
class LookupController extends AdminController
{
/**
* Return an index of entries from related stream.
*
* @param Container $container
* @param $key
* @return \Symfony\Component\HttpFoundation\Response
*/
public function index(Container $container, $key)
{
/* @var Collection $config */
$config = $this->dispatch(new GetConfiguration($key));
$related = $container->make($config->get('related'));
if ($table = $config->get('lookup_table')) {
$table = $container->make($table);
} else {
$table = $related->newMultipleFieldTypeLookupTableBuilder();
}
/* @var LookupTableBuilder $table */
$table->setConfig($config)
->setModel($related);
return $table->render();
}
/**
* @param Container $container
* @param MultipleFieldType $fieldType
* @param $key
*/
public function json(Container $container, MultipleFieldType $fieldType, $key)
{
/* @var Collection $config */
$config = $this->dispatch(new GetConfiguration($key));
$fieldType->mergeConfig($config->all());
/* @var EloquentModel $model */
$model = $container->make($config->get('related'));
$data = [];
/* @var EntryInterface $item */
foreach ($model->all() as $item) {
$data[] = (object)[
'id' => $item->getId(),
'text' => $item->getTitle(),
];
}
return $this->response->json($data);
}
/**
* Return the selected entries.
*
* @param SelectedTableBuilder $table
* @param MultipleFieldType $fieldType
* @param $key
* @return null|string
*/
public function selected(Container $container, MultipleFieldType $fieldType, $key)
{
/* @var Collection $config */
$config = $this->dispatch(new GetConfiguration($key));
$fieldType->mergeConfig($config->all());
$fieldType->setField($config->get('field'));
$fieldType->setEntry($this->container->make($config->get('entry')));
$related = $container->make($config->get('related'));
if ($table = $config->get('selected_table')) {
$table = $container->make($table);
} else {
$table = $related->newMultipleFieldTypeSelectedTableBuilder();
}
/* @var SelectedTableBuilder $table */
$table->setSelected(array_filter(explode(',', $this->request->get('uploaded'))))
->setModel($config->get('related'))
->setFieldType($fieldType)
->setConfig($config)
->build()
->load();
return $table->getTableContent();
}
}

View File

@ -0,0 +1,357 @@
<?php namespace Visiosoft\MultipleFieldType;
use Visiosoft\MultipleFieldType\Command\BuildOptions;
use Visiosoft\MultipleFieldType\Table\ValueTableBuilder;
use Anomaly\Streams\Platform\Addon\FieldType\FieldType;
use Anomaly\Streams\Platform\Entry\EntryCollection;
use Anomaly\Streams\Platform\Model\EloquentCollection;
use Anomaly\Streams\Platform\Model\EloquentModel;
use Anomaly\Streams\Platform\Stream\Command\GetStream;
use Anomaly\Streams\Platform\Support\Collection;
use Anomaly\Streams\Platform\Ui\Form\FormBuilder;
use Illuminate\Container\Container;
use Illuminate\Contracts\Cache\Repository;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Facades\Crypt;
class MultipleFieldType extends FieldType
{
use DispatchesJobs;
/**
* No database column.
*
* @var bool
*/
protected $columnType = false;
/**
* The input view.
*
* @var string
*/
protected $inputView = null;
/**
* The filter view.
*
* @var string
*/
protected $filterView = 'visiosoft.field_type.multiple::filter';
/**
* The pre-defined handlers.
*
* @var array
*/
protected $handlers = [
'related' => 'Visiosoft\MultipleFieldType\Handler\Related@handle',
//'fields' => 'Visiosoft\MultipleFieldType\Handler\Fields@handle',
//'assignments' => 'Visiosoft\MultipleFieldType\Handler\Assignments@handle'
];
/**
* The field type rules.
*
* @var array
*/
protected $rules = [
'array',
];
/**
* The field type config.
*
* @var array
*/
protected $config = [
'mode' => 'tags',
];
/**
* The select input options.
*
* @var null|array
*/
protected $options = null;
/**
* The cache repository.
*
* @var Repository
*/
protected $cache;
/**
* The service container.
*
* @var Container
*/
protected $container;
/**
* Create a new MultipleFieldType instance.
*
* @param Repository $cache
* @param Container $container
*/
public function __construct(Repository $cache, Container $container)
{
$this->cache = $cache;
$this->container = $container;
}
/**
* Return the ids.
*
* @return array|mixed|static
*/
public function ids()
{
$value = $this->getValue();
if (is_object($value)) {
$value = $value->pluck('id')->all();
}
return array_filter((array)$value);
}
/**
* Get the rules.
*
* @return array
*/
public function getRules()
{
$rules = parent::getRules();
if ($min = array_get($this->getConfig(), 'min')) {
$rules[] = 'min:' . $min;
}
if ($max = array_get($this->getConfig(), 'max')) {
$rules[] = 'max:' . $max;
}
return $rules;
}
/**
* Return the config key.
*
* @return string
*/
public function key()
{
return Crypt::encrypt(array_merge(
$this->getConfig(),
[
'field' => $this->getField(),
'entry' => get_class($this->getEntry()),
]
));
}
/**
* Value table.
*
* @return string
*/
public function table()
{
$value = $this->getValue();
$related = $this->getRelatedModel();
if ($table = $this->config('value_table')) {
$table = $this->container->make($table);
} else {
$table = $related->newMultipleFieldTypeValueTableBuilder();
}
/* @var ValueTableBuilder $table */
$table->setConfig(new Collection($this->getConfig()))
->setFieldType($this)
->setModel($related);
if (!$value instanceof EntryCollection) {
$table->setSelected((array)$value);
}
if ($value instanceof EntryCollection) {
$table->setSelected($value->ids());
}
return $table
->build()
->load()
->getTableContent();
}
/**
* Get the relation.
*
* @return BelongsToMany
*/
public function getRelation()
{
$entry = $this->getEntry();
$model = $this->getRelatedModel();
return $entry->belongsToMany(
get_class($model),
$this->getPivotTableName(),
'entry_id',
'related_id'
)->orderBy($this->getPivotTableName() . '.sort_order', 'ASC');
}
/**
* Get the options.
*
* @return array
*/
public function getOptions()
{
if ($this->options === null) {
$this->dispatch(new BuildOptions($this));
}
return $this->options;
}
/**
* Set the options.
*
* @param array $options
* @return $this
*/
public function setOptions(array $options)
{
$this->options = $options;
return $this;
}
/**
* Get the pre-defined handlers.
*
* @return array
*/
public function getHandlers()
{
return $this->handlers;
}
/**
* Return the input view.
*
* @return string
*/
public function getInputView()
{
return $this->inputView ?: 'visiosoft.field_type.multiple::' . $this->config('mode');
}
/**
* Get the related model.
*
* @return EloquentModel
*/
public function getRelatedModel()
{
$model = $this->config('related');
if (strpos($model, '.')) {
/* @var StreamInterface $stream */
$stream = $this->dispatch(new GetStream($model));
return $stream->getEntryModel();
}
return $this->container->make($model);
}
/**
* Get the pivot table.
*
* @return string
*/
public function getPivotTableName()
{
return $this->entry->getTableName() . '_' . $this->getField();
}
/**
* Get the post value.
*
* @param null $default
* @return array
*/
public function getPostValue($default = null)
{
if (is_array($value = parent::getPostValue($default))) {
return array_filter($value);
}
return array_filter(explode(',', $value));
}
/**
* Get the class.
*
* @return null|string
*/
public function getClass()
{
if ($class = parent::getClass()) {
return $class;
}
return $this->config('mode') == 'dropdown' ? 'custom-select form-control' : null;
}
/**
* Handle saving the form data ourselves.
*
* @param FormBuilder $builder
*/
public function handle(FormBuilder $builder)
{
$entry = $builder->getFormEntry();
// See the accessor for how IDs are handled.
$entry->{$this->getField()} = $this->getPostValue();
}
/**
* Fired just before version comparison.
*
* @param EloquentCollection $related
*/
public function toArrayForComparison(EloquentCollection $related)
{
return $related->map(
function (EloquentModel $model) {
return array_diff_key(
$model->toArrayWithRelations(),
array_flip(
[
'id',
'sort_order',
'created_at',
'created_by_id',
'updated_at',
'updated_by_id',
'deleted_at',
'deleted_by_id',
]
)
);
}
)->toArray();
}
}

View File

@ -0,0 +1,97 @@
<?php namespace Visiosoft\MultipleFieldType;
use Anomaly\Streams\Platform\Addon\FieldType\FieldTypeAccessor;
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
use Illuminate\Database\Eloquent\Collection;
class MultipleFieldTypeAccessor extends FieldTypeAccessor
{
/**
* The field type object.
* This is for IDE support.
*
* @var MultipleFieldType
*/
protected $fieldType;
/**
* Set the value.
*
* @param $value
*/
public function set($value)
{
if (is_string($value)) {
$value = $this->organizeSyncValue(explode(',', $value));
} elseif (is_array($value)) {
$value = $this->organizeSyncValue($value);
} elseif ($value instanceof Collection) {
$value = $this->organizeSyncValue($value->filter()->all());
} elseif ($value instanceof EntryInterface) {
$value = $this->organizeSyncValue([$value->getId()]);
}
if (!$value) {
$this->fieldType->getRelation()->detach();
return;
}
$this->fieldType->getRelation()->sync($value);
}
/**
* Organize the value for sync.
*
* @param array $value
* @return array
*/
protected function organizeSyncValue(array $value)
{
/**
* First clean our value.
*/
$value = array_filter(array_unique($value));
/**
* Next take the natural array
* key and make it the sort order.
*/
$value = array_combine(
array_values($value),
array_map(
function ($key) {
return [
'sort_order' => $key,
];
},
array_keys($value)
)
);
/**
* Lastly add the file_id
* relation column for sync.
*/
array_walk(
$value,
function (&$value, $key) {
$value['related_id'] = $key;
}
);
return $value;
}
/**
* Get the value.
*
* @return mixed
*/
public function get()
{
return $this->fieldType->getRelation();
}
}

View File

@ -0,0 +1,27 @@
<?php namespace Visiosoft\MultipleFieldType;
use Anomaly\Streams\Platform\Addon\FieldType\FieldTypeQuery;
use Anomaly\Streams\Platform\Ui\Table\Component\Filter\Contract\FilterInterface;
use Illuminate\Database\Eloquent\Builder;
class MultipleFieldTypeQuery extends FieldTypeQuery
{
/**
* Handle the filter query.
*
* @param Builder $query
* @param FilterInterface $filter
*/
public function filter(Builder $query, FilterInterface $filter)
{
$stream = $filter->getStream();
$query->leftJoin(
$stream->getEntryTableName() . '_' . $filter->getField() . ' AS filter_' . $filter->getField(),
$stream->getEntryTableName() . '.id',
'=',
'filter_' . $filter->getField() . '.entry_id'
)->where('filter_' . $filter->getField() . '.related_id', $filter->getValue());
}
}

Some files were not shown because too many files have changed in this diff Show More