Skip to content

Commit

Permalink
Collection table dyanmic table form
Browse files Browse the repository at this point in the history
  • Loading branch information
MuchQuak committed Dec 17, 2024
1 parent ee54c46 commit 930ce2f
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 17 deletions.
5 changes: 5 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public function boot(): void {
});
}

// Helper Macro to Progate Apline binds from parent component to subcomponent within blade. This May be required if you have dynamic names from generated input fields.
Blade::directive('bind', function($expression) {
return '<?php echo $attributes["x-bind:" . "'. $expression.'"] ? \'x-bind:\'. "' . $expression . '" . \'="\' . $attributes["x-bind:" . "'. $expression.'"] . \'"\': "" ?>';
});

Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
$event->extendSocialite('orcid', \App\Socialite\Orcid\Provider::class);
});
Expand Down
80 changes: 80 additions & 0 deletions resources/views/core/occurrence-attribute-select.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
@php
$items = [
['title'=> 'Associated Collectors', 'value' => 'associatedCollectors', 'disabled' => false ],
['title'=> 'Associated Occurrences', 'value' => 'associatedOccurrences', 'disabled' => false ],
['title'=> 'Associated Taxa', 'value' => 'associatedTaxa', 'disabled' => false ],
['title'=> 'Attributes', 'value' => 'attributes', 'disabled' => false ],
['title'=> 'Author', 'value' => 'scientificNameAuthorship', 'disabled' => false ],
['title'=> 'Basis Of Record', 'value' => 'basisOfRecord', 'disabled' => false ],
['title'=> 'Behavior', 'value' => 'behavior', 'disabled' => false ],
['title'=> 'Catalog Number', 'value' => 'catalogNumber', 'disabled' => false ],
['title'=> 'Collection Code (override)', 'value' => 'collectionCode', 'disabled' => false ],
['title'=> 'Collector Number', 'value' => 'recordNumber', 'disabled' => false ],
['title'=> 'Collector/Observer', 'value' => 'recordedBy', 'disabled' => false ],
['title'=> 'Coordinate Uncertainty (m)', 'value' => 'coordinateUncertaintyInMeters', 'disabled' => false ],
['title'=> 'Country', 'value' => 'country', 'disabled' => false ],
['title'=> 'County', 'value' => 'county', 'disabled' => false ],
['title'=> 'Cultivation Status', 'value' => 'cultivationStatus', 'disabled' => false ],
['title'=> 'Data Generalizations', 'value' => 'dataGeneralizations', 'disabled' => false ],
['title'=> 'Date', 'value' => 'eventDate', 'disabled' => false ],
['title'=> 'Date Entered', 'value' => 'dateEntered', 'disabled' => false ],
['title'=> 'Date Last Modified', 'value' => 'dateLastModified', 'disabled' => false ],
['title'=> 'dbpk', 'value' => 'dbpk', 'disabled' => false ],
['title'=> 'Decimal Latitude', 'value' => 'decimalLatitude', 'disabled' => false ],
['title'=> 'Decimal Longitude', 'value' => 'decimalLongitude', 'disabled' => false ],
['title'=> 'Depth Maximum (m)', 'value' => 'maximumDepthInMeters', 'disabled' => false ],
['title'=> 'Depth Minimum (m)', 'value' => 'minimumDepthInMeters', 'disabled' => false ],
['title'=> 'Description', 'value' => 'verbatimAttributes', 'disabled' => false ],
['title'=> 'Disposition', 'value' => 'disposition', 'disabled' => false ],
['title'=> 'Dynamic Properties', 'value' => 'dynamicProperties', 'disabled' => false ],
['title'=> 'Elevation Maximum (m)', 'value' => 'maximumElevationInMeters', 'disabled' => false ],
['title'=> 'Elevation Minimum (m)', 'value' => 'minimumElevationInMeters', 'disabled' => false ],
['title'=> 'Establishment Means', 'value' => 'establishmentMeans', 'disabled' => false ],
['title'=> 'Family', 'value' => 'family', 'disabled' => false ],
['title'=> 'Field Notes', 'value' => 'fieldNotes', 'disabled' => false ],
['title'=> 'Field Number', 'value' => 'fieldnumber', 'disabled' => false ],
['title'=> 'Geodetic Datum', 'value' => 'geodeticDatum', 'disabled' => false ],
['title'=> 'Georeference Protocol', 'value' => 'georeferenceProtocol', 'disabled' => false ],
['title'=> 'Georeference Remarks', 'value' => 'georeferenceRemarks', 'disabled' => false ],
['title'=> 'Georeference Sources', 'value' => 'georeferenceSources', 'disabled' => false ],
['title'=> 'Georeference Verification Status', 'value' => 'georeferenceVerificationStatus', 'disabled' => false ],
['title'=> 'Georeferenced By', 'value' => 'georeferencedBy', 'disabled' => false ],
['title'=> 'Habitat', 'value' => 'habitat', 'disabled' => false ],
['title'=> 'Identification Qualifier', 'value' => 'identificationQualifier', 'disabled' => false ],
['title'=> 'Identification References', 'value' => 'identificationReferences', 'disabled' => false ],
['title'=> 'Identification Remarks', 'value' => 'identificationRemarks', 'disabled' => false ],
['title'=> 'Identified By', 'value' => 'identifiedBy', 'disabled' => false ],
['title'=> 'Individual Count', 'value' => 'individualCount', 'disabled' => false ],
['title'=> 'Information Withheld', 'value' => 'informationWithheld', 'disabled' => false ],
['title'=> 'Institution Code (override)', 'value' => 'institutionCode', 'disabled' => false ],
['title'=> 'Label Project', 'value' => 'labelProject', 'disabled' => false ],
['title'=> 'Language', 'value' => 'language', 'disabled' => false ],
['title'=> 'Life Stage', 'value' => 'lifeStage', 'disabled' => false ],
['title'=> 'Location ID', 'value' => 'locationid', 'disabled' => false ],
['title'=> 'Locality', 'value' => 'locality', 'disabled' => false ],
['title'=> 'Locality Security', 'value' => 'localitySecurity', 'disabled' => false ],
['title'=> 'Locality Security Reason', 'value' => 'localitySecurityReason', 'disabled' => false ],
['title'=> 'Location Remarks', 'value' => 'locationRemarks', 'disabled' => false ],
['title'=> 'Modified By', 'value' => 'username', 'disabled' => false ],
['title'=> 'Municipality', 'value' => 'municipality', 'disabled' => false ],
['title'=> 'Notes (Occurrence Remarks)', 'value' => 'occurrenceRemarks', 'disabled' => false ],
['title'=> 'OCR Fragment', 'value' => 'ocrFragment', 'disabled' => false ],
['title'=> 'Other Catalog Numbers', 'value' => 'otherCatalogNumbers', 'disabled' => false ],
['title'=> 'Owner Code', 'value' => 'ownerInstitutionCode', 'disabled' => false ],
['title'=> 'Preparations', 'value' => 'preparations', 'disabled' => false ],
['title'=> 'Reproductive Condition', 'value' => 'reproductiveCondition', 'disabled' => false ],
['title'=> 'Sampling Effort', 'value' => 'samplingEffort', 'disabled' => false ],
['title'=> 'Sampling Protocol', 'value' => 'samplingProtocol', 'disabled' => false ],
['title'=> 'Scientific Name', 'value' => 'sciname', 'disabled' => false ],
['title'=> 'Sex', 'value' => 'sex', 'disabled' => false ],
['title'=> 'State/Province', 'value' => 'stateProvince', 'disabled' => false ],
['title'=> 'Substrate', 'value' => 'substrate', 'disabled' => false ],
['title'=> 'Taxon Remarks', 'value' => 'taxonRemarks', 'disabled' => false ],
['title'=> 'Type Status', 'value' => 'typeStatus', 'disabled' => false ],
['title'=> 'Verbatim Coordinates', 'value' => 'verbatimCoordinates', 'disabled' => false ],
['title'=> 'Verbatim Date', 'value' => 'verbatimEventDate', 'disabled' => false ],
['title'=> 'Verbatim Depth', 'value' => 'verbatimDepth', 'disabled' => false ],
['title'=> 'Verbatim Elevation', 'value' => 'verbatimElevation', 'disabled' => false ],
];
@endphp
<x-select :items="$items" {{ $attributes }} />
92 changes: 83 additions & 9 deletions resources/views/core/pages/collections/table.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,50 @@ function getOccurrenceEditorUrl($other_params) {
return $base_url . $query;
}
$custom_fields = [];
for($i = 1; $i < 10; $i++) {
$type = request('q_customtype' . $i);
$field = request('q_customfield' . $i);
$value = request('q_customvalue' . $i);
if($type && $field && $value) {
array_push($custom_fields,[
[
'id' => $i,
'type' => $type,
'field' => $value,
'value' => $field,
]
]);
}
}
if(count($custom_fields) === 0) {
$custom_fields = [
[
'id' => 1,
'type' => 'EQUALS',
'field' => NULL,
'value' => "",
]
];
}
@endphp
<x-layout class="p-0 h-[100vh] relative" x-data="{ menu_open: false}" :hasFooter="false" :hasHeader="false"
<x-layout class="p-0 h-[100vh] relative" x-data="{ menu_open: true }" :hasFooter="false" :hasHeader="false"
:hasNavbar="false">
<div class="pt-4 px-4 flex flex-col gap-2 h-[7rem] relative">
<x-breadcrumbs :items="[
['title' => 'Home'],
['title' => 'Collection Management', 'href' => url(config('portal.name') . '/collections/misc/collprofiles.php?emode=1&collid='. request('collid'))],
['title' => 'Occurrence Table view'],
]" />
['title' => 'Home'],
['title' => 'Collection Management', 'href' => url(config('portal.name') . '/collections/misc/collprofiles.php?emode=1&collid='. request('collid'))],
['title' => 'Occurrence Table view'],
]" />
<div class="text-2xl text-primary font-bold">
{{$collection->collectionName}} ({{$collection->institutionCode}})
</div>

<x-button x-on:click="menu_open = true" class="w-fit absolute right-4">Adjust Search</x-button>
</div>

<div class="absolute h-screen w-1/2 min-w-[40rem] bg-base-100 z-[100] top-0 left-0" x-cloak x-show="menu_open">
<div class="absolute h-screen w-full min-w-[40rem] bg-base-100 z-[100] top-0 left-0" x-cloak x-show="menu_open">
<button x-on:click="menu_open = false"
class="float-right mr-2 mt-2 hover:ring-4 focus:outline-none focus:ring-4 rounded-md w-6 h-6 ring-accent">
<i class="cursor-pointer fa fas fa-close"></i>
Expand Down Expand Up @@ -114,9 +141,56 @@ class="float-right mr-2 mt-2 hover:ring-4 focus:outline-none focus:ring-4 rounde
['title' => 'Select Exsiccati', 'value' => null, 'disabled' => false]
]" />
@endif
<div class="text-2xl font-bold w-full py-10 text-center bg-base-200">
TODO CUSTOM FILTERS

<div x-data="{ data: {{ json_encode($custom_fields) }} }" class="flex flex-col gap-4">
<template x-for="(d, index) of data" :key="'custom-form-' + index">
<div>
<div>
Custom Field <span x-text="index + 1"></span>
</div>
<div class="flex flex-row gap-4 items-center">
{{--
<x-select x-bind:name="'q_customopenparen' + (index + 1)" :default="0" :items="[
['title' => '---', 'value' => null, 'disabled' => false],
['title' => '(', 'value' => '(', 'disabled' => false],
['title' => '((', 'value' => '((', 'disabled' => false],
['title' => '(((', 'value' => '(((', 'disabled' => false],
]"/>
--}}
<x-occurrence-attribute-select x-bind:name="'q_customfield' + (index + 1)" class="min-w-72" :select_text="'Select Field Name'" />
<x-select class="min-w-72" x-bind:value="data && data[index]? data[index].type:'EQUALS'" x-on:change='data[index].type = $event.target.type;' x-bind:name="'q_customtype' + (index + 1)" :items="[
['title'=> 'EQUALS', 'value' => 'EQUALS', 'disabled' => false ],
['title'=> 'NOT EQUALS', 'value' => 'NOT_EQUALS', 'disabled' => false ],
['title'=> 'STARTS WITH', 'value' => 'STARTS_WITH', 'disabled' => false ],
['title'=> 'CONTAINS', 'value' => 'LIKE', 'disabled' => false ],
['title'=> 'DOES NOT CONTAIN', 'value' => 'NOT_LIKE', 'disabled' => false ],
['title'=> 'GREATER THAN', 'value' => 'GREATER_THAN', 'disabled' => false ],
['title'=> 'LESS THAN', 'value' => 'LESS_THAN', 'disabled' => false ],
['title'=> 'IS NULL', 'value' => 'IS_NULL', 'disabled' => false ],
['title'=> 'IS NOT NULL', 'value' => 'NOT_NULL', 'disabled' => false ],
]"/>
<x-input x-bind:name="'q_customvalue' + (index + 1)" x-bind:value="data && data[index]? data[index].value: ''" x-on:change='data[index].value = $event.target.value;'/>

{{--
<x-select x-bind:name="'q_customclosedparen' + (index + 1)" :default="0" :items="[
['title' => '---', 'value' => null, 'disabled' => false],
['title' => ')', 'value' => ')', 'disabled' => false],
['title' => '))', 'value' => '))', 'disabled' => false],
['title' => ')))', 'value' => ')))', 'disabled' => false],
]"/>
--}}

<x-button type="button" @click="data.splice(index, 1)">
<i class="fa fa-minus"></i>
</x-button>
</div>
</div>
</template>
<x-button type="button" @click="if(data.length < 10) data.push([{type: 'EQUALS', field: null, value: ''}])">
<i class="fa fa-plus"></i> Add Custom Field
</x-button>
</div>

@if(false)
<div class="flex gap-4 items-center">
<x-select id="sort" class="w-full" label="Sort By" :items="[
Expand Down
32 changes: 24 additions & 8 deletions resources/views/core/select.blade.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
@props([
'items' => [],
'name' => 'select',
'name' => null,
'label' => null,
'default' => 0,
'default' => null,
'defaultValue' => null,
'id' => uniqid(),
'labeledBy' => null
'bind_id' => false,
'labeledBy' => null,
'select_text' => 'Select Item'
])
@php
if($defaultValue && !$default) {
for($i = 0; $i < count($items); $i++) {
$item = $items[$i];
if($item && $item['value'] === $defaultValue) {
$default = $i;
break;
}
echo $item['value'];
}
}
@endphp

<div {{ $attributes->withoutTwMergeClasses()->twMerge("w-fit h-fit")}}>
@if($label ?? false)
<label class="text" id="{{ $id }}-label" for="{{ $id }}-toggle">{{ $label }}</label>
@endif
<div x-data="{
selectOpen: false,
selectedItem: {{ ($default >= 0 && $items && $items[$default])? json_encode($items[$default]) : "''"}},
selectedItem: {{ ($default !== null && $default >= 0 && $items && $items[$default])? json_encode($items[$default]) : "''"}},
selectableItems: {{ json_encode($items) }},
selectableItemActive: null,
selectId: $id('select'),
Expand Down Expand Up @@ -73,7 +88,7 @@
},
selectItemsFindBestMatch(){
typedValue = this.selectKeydownValue.toLowerCase();
var bestMatch = null;Lpbobbystar360$
var bestMatch = null;
var bestMatchIndex = -1;
for (var i = 0; i < this.selectableItems.length; i++) {
var title = this.selectableItemsLpbobbystar360$[i].title.toLowerCase();
Expand Down Expand Up @@ -120,12 +135,13 @@
{{ $attributes->twMergeFor('button', 'relative min-h-[38px] flex items-center justify-between w-full py-2 pl-3 pr-10 text-left bg-base-100 border rounded-md shadow-sm cursor-default border-base-300 focus:outline-none cursor-pointer' )}}
>

<span x-text="selectedItem ? selectedItem.title : 'Select Item'" class="truncate">Select Item</span>
<span x-text="selectedItem ? selectedItem.title : '{{ $select_text }}'" class="truncate">{{ $select_text }}</span>
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="w-5 h-5 text-base-content/50"><path fill-rule="evenodd" d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z" clip-rule="evenodd"></path></svg>
</span>
<input id="{{ $id }}" type="hidden" name="{{ $name }}" x-bind:value="selectedItem ? selectedItem.value: null"/>
<input id="{{ $id }}" type="hidden" name="{{ $name ?? $id }}" x-bind:value="selectedItem ? selectedItem.value: null" @bind(id) @bind(name) x-on:change=""/>
</button>

<ul x-show="selectOpen"
x-ref="selectableItemsList"
@click.away="selectOpen = false"
Expand All @@ -136,7 +152,7 @@
class="absolute w-full py-1 z-10 mt-1 overflow-auto bg-white rounded-md shadow-md max-h-56 ring-1 ring-black ring-opacity-5 focus:outline-none"
x-cloak>

<template x-for="item in selectableItems" :key="item.value">
<template x-for="(item, index) in selectableItems" :key="index + '-' + item.value">
<li
@click="selectedItem=item; selectOpen=false; $refs.selectButton.focus();"
:id="item.value + '-' + selectId"
Expand Down
51 changes: 51 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,57 @@
}
}

for ($i=1; $i < 10; $i++) {
$custom_field = $request->query('q_customfield' . $i);
$type = $request->query('q_customtype' . $i);
$value= $request->query('q_customvalue' . $i);

if(!$custom_field) continue;

if (($idx = array_search($custom_field, $sortables)) > 0) {
switch ($type) {
case 'EQUALS':
$query->where('o.' . $sortables[$idx], '=', $value);
break;
case 'NOT_EQUALS':
$query->where('o.' . $sortables[$idx], '!=', $value);
break;

case 'START_WITH':
$query->whereLike('o.' . $sortables[$idx], '%' . $value);
break;

case 'CONTAINS':
$query->whereLike('o.' . $sortables[$idx], '%' . $value . '%');
break;

case 'DOES_NOT_CONTAIN':
$query->whereNotLike('o.' . $sortables[$idx], '%' . $value . '%');
break;

case 'GREATER_THAN':
$query->where('o.' . $sortables[$idx], '>', $value);
break;

case 'LESS_THAN':
$query->where('o.' . $sortables[$idx], '<', $value);
break;

case 'IS_NULL':
$query->whereNull('o.' . $sortables[$idx]);
break;

case 'NOT_NULL':
$query->whereNotNull('o.');
break;

default:
break;
}
$query->orderByRaw('ISNULL(o.' . $sortables[$idx] . ') ASC');
}
}

if ($request->query('sort')) {
if (($idx = array_search($request->query('sort'), $sortables)) > 0) {
$query->orderByRaw('ISNULL(o.' . $sortables[$idx] . ') ASC');
Expand Down

0 comments on commit 930ce2f

Please sign in to comment.