feat: project search on frontend
This commit is contained in:
@@ -24,6 +24,8 @@ class Project extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $appends = ['default_environment'];
|
||||
|
||||
public static function ownedByCurrentTeam()
|
||||
{
|
||||
return Project::whereTeamId(currentTeam()->id)->orderBy('name');
|
||||
@@ -131,7 +133,7 @@ class Project extends BaseModel
|
||||
return $this->postgresqls()->get()->merge($this->redis()->get())->merge($this->mongodbs()->get())->merge($this->mysqls()->get())->merge($this->mariadbs()->get())->merge($this->keydbs()->get())->merge($this->dragonflies()->get())->merge($this->clickhouses()->get());
|
||||
}
|
||||
|
||||
public function default_environment()
|
||||
public function getDefaultEnvironmentAttribute()
|
||||
{
|
||||
$default = $this->environments()->where('name', 'production')->first();
|
||||
if ($default) {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@foreach ($projects as $project)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group"
|
||||
onclick="gotoProject('{{ $project->uuid }}','{{ $project->default_environment() }}')">
|
||||
onclick="gotoProject('{{ $project->uuid }}','{{ $project->default_environment }}')">
|
||||
<div class="flex flex-1 mx-6">
|
||||
<div class="flex flex-col justify-center flex-1">
|
||||
<div class="box-title">{{ $project->name }}</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-2 text-xs font-bold">
|
||||
<a class="hover:underline"
|
||||
href="{{ route('project.resource.create', ['project_uuid' => $project->uuid, 'environment_name' => data_get($project, 'default_environment()', 'production')]) }}">
|
||||
href="{{ route('project.resource.create', ['project_uuid' => $project->uuid, 'environment_name' => data_get($project, 'default_environment', 'production')]) }}">
|
||||
<span class="p-2 font-bold">+ Add Resource</span>
|
||||
</a>
|
||||
<a class="hover:underline"
|
||||
|
||||
@@ -9,35 +9,59 @@
|
||||
</x-modal-input>
|
||||
</div>
|
||||
<div class="subtitle">All your projects are here.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
@forelse ($projects as $project)
|
||||
<div class="box group" onclick="gotoProject('{{ $project->uuid }}', '{{ $project->default_environment() }}')">
|
||||
<div class="flex flex-col justify-center flex-1 mx-6">
|
||||
<div class="box-title">{{ $project->name }}</div>
|
||||
<div class="box-description ">
|
||||
{{ $project->description }}</div>
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input placeholder="Search for name, description..." x-model="search" id="null" />
|
||||
<div class="grid grid-cols-2 gap-4 pt-4">
|
||||
<template x-if="allFilteredItems.length === 0">
|
||||
<div>No project found with the search term "<span x-text="search"></span>".</div>
|
||||
</template>
|
||||
|
||||
<template x-for="item in allFilteredItems" :key="item.uuid">
|
||||
<div class="box group" @click="gotoProject(item)">
|
||||
<div class="flex flex-col justify-center flex-1 mx-6">
|
||||
<div class="box-title" x-text="item.name"></div>
|
||||
<div class="box-description ">
|
||||
<div x-text="item.description"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-2 pt-4 pb-2 mr-4 text-xs lg:py-0 lg:justify-normal">
|
||||
<a class="mx-4 font-bold hover:underline"
|
||||
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div>
|
||||
<div>No project found.</div>
|
||||
</div>
|
||||
@endforelse
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function gotoProject(uuid, environment) {
|
||||
if (environment) {
|
||||
window.location.href = '/project/' + uuid + '/' + environment;
|
||||
} else {
|
||||
window.location.href = '/project/' + uuid;
|
||||
function sortFn(a, b) {
|
||||
return a.name.localeCompare(b.name)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
function searchComponent() {
|
||||
return {
|
||||
search: '',
|
||||
projects: @js($projects),
|
||||
filterAndSort(items) {
|
||||
if (this.search === '') {
|
||||
return Object.values(items).sort(sortFn);
|
||||
}
|
||||
const searchLower = this.search.toLowerCase();
|
||||
return Object.values(items).filter(item => {
|
||||
return (item.name?.toLowerCase().includes(searchLower) ||
|
||||
item.description?.toLowerCase().includes(searchLower))
|
||||
}).sort(sortFn);
|
||||
},
|
||||
get allFilteredItems() {
|
||||
return [
|
||||
this.projects,
|
||||
].flatMap((items) => this.filterAndSort(items));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gotoProject(item) {
|
||||
if (item.default_environment) {
|
||||
window.location.href = '/project/' + item.uuid + '/' + item.default_environment;
|
||||
} else {
|
||||
window.location.href = '/project/' + item.uuid;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input placeholder="Search for name, fqdn..." x-model="search" id="null" />
|
||||
<div class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<template x-if="allFilteredItems.length === 0">
|
||||
<div>No resource found with the search term "<span x-text="search"></span>".</div>
|
||||
</template>
|
||||
|
||||
<template x-for="item in allFilteredItems" :key="item.uuid">
|
||||
<span>
|
||||
<a class="h-24 box group" :href="item.hrefLink">
|
||||
|
||||
Reference in New Issue
Block a user