filters and sidebar

This commit is contained in:
2024-08-15 14:44:53 +03:00
parent 1f3ebafe69
commit f9806f60c9
32 changed files with 584 additions and 456 deletions
+20
View File
@@ -30,3 +30,23 @@ export function stripHtml(html = "") {
export function randomId(length = 10) { export function randomId(length = 10) {
return Math.random().toString(36).substring(2, length + 2); return Math.random().toString(36).substring(2, length + 2);
} }
export function clickOutside(node) {
const handleClick = event => {
if (node && !node.contains(event.target) && !event.defaultPrevented) {
node.dispatchEvent(
new CustomEvent('click_outside', node)
)
}
}
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
}
}
+11 -2
View File
@@ -4,9 +4,10 @@
import RecordEdit from "./records/Edit.svelte"; import RecordEdit from "./records/Edit.svelte";
import ContentIndex from "./content/Index.svelte"; import ContentIndex from "./content/Index.svelte";
import {setContext} from "svelte"; import {setContext} from "svelte";
import Navbar from "./Navbar.svelte"; import Navbar from "./layout/Navbar.svelte";
import HomeIndex from "./home/Index.svelte"; import HomeIndex from "./home/Index.svelte";
import BuildReport from "./build/Report.svelte"; import BuildReport from "./build/Report.svelte";
import Header from "./layout/Header.svelte";
const components = { const components = {
members: Members, members: Members,
@@ -35,7 +36,15 @@
</script> </script>
<div class="main-wrapper">
<div class="sidebar-content">
<Navbar schema={data.schema}/> <Navbar schema={data.schema}/>
</div>
<div class="main-content">
<Header />
<svelte:component this={components[view]} {title} {...data}/> <svelte:component this={components[view]} {title} {...data}/>
</div>
</div>
-126
View File
@@ -1,126 +0,0 @@
<script>
import Avatar from "./account/Avatar.svelte";
import NavbarMenu from "./NavbarMenu.svelte";
import {getContext} from "svelte";
export let schema;
const channel = getContext("channel");
const readableSchemas = getContext("readableSchemas");
const user = getContext("user");
let contentIsOpen = false;
const fileSchemas = readableSchemas.filter((sc) => sc.type === "files");
const otherSchemas = readableSchemas.filter((sc) => !sc.isEntry && sc.type === "collection");
let filesIsActive = false;
let otherIsActive = false;
if(schema){
filesIsActive = fileSchemas.filter(s => s.name === schema.name).length > 0;
otherIsActive = otherSchemas.filter(s => s.name === schema.name).length > 0;
}
</script>
<nav class="lx-nav">
<div>
<button on:click={(e) => contentIsOpen = true} class="btn btn-primary btn-sm d-xxl-none">« Content</button>
</div>
<div class="d-flex align-items-center ">
<a class="nav-item" href="{channel.lucentUrl}">{channel.name}</a>
<a class="nav-item" href="{channel.lucentUrl}/members">Members</a>
{#if channel.generateCommand}
<a href="{channel.lucentUrl}/build-report" class="btn btn-outline-primary btn-sm d-">Build website</a>
{/if}
<!-- <div>-->
<!-- <form method="GET">-->
<!-- <input type="search" name="filter[search_regex]" placeholder="Search"-->
<!-- class="form-control" required/>-->
<!-- </form>-->
<!-- </div>-->
</div>
<div>
<a class="nav-item" href="{channel.lucentUrl}/profile">
<Avatar side="28" name={user.name}/>
</a>
</div>
</nav>
<div class="offcanvas offcanvas-start d-xxl-block show border-0 bg-light-subtle" class:d-none={!contentIsOpen}
style="padding-top:36px " data-bs-scroll="true"
data-bs-backdrop="false"
tabindex="-1" aria-labelledby="offcanvasScrollingLabel">
<!-- <div class="offcanvas-header">-->
<!-- <h5 class="offcanvas-title" id="offcanvasScrollingLabel">Content</h5>-->
<!-- </div>-->
<div class="offcanvas-body">
<button on:click={(e) => contentIsOpen = false} class="btn btn-primary btn-sm d-xxl-none mb-4">« close</button>
<div class="accordion">
<div class="accordion-item">
<h2 class="accordion-header" id="panelsStayOpen-headingMain">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#panelsStayOpen-collapseMain" aria-expanded="true"
aria-controls="panelsStayOpen-collapseMain">
Main
</button>
</h2>
<div id="panelsStayOpen-collapseMain" class="accordion-collapse collapse show"
aria-labelledby="panelsStayOpen-headingMain">
<div class="accordion-body">
<NavbarMenu
schemas={ readableSchemas.filter((sc) => sc.isEntry)}
schema={schema}
/>
</div>
</div>
</div>
{#if otherSchemas.length > 0}
<div class="accordion-item">
<h2 class="accordion-header" id="panelsStayOpen-headingOther">
<button class="accordion-button" class:collapsed={!otherIsActive} type="button" data-bs-toggle="collapse"
data-bs-target="#panelsStayOpen-collapseOther" aria-expanded={otherIsActive}
aria-controls="panelsStayOpen-collapseOther">
Other
</button>
</h2>
<div id="panelsStayOpen-collapseOther" class="accordion-collapse collapse"
class:show={otherIsActive}
aria-labelledby="panelsStayOpen-headingOther">
<div class="accordion-body">
<NavbarMenu
schemas={ otherSchemas}
schema={schema}
/>
</div>
</div>
</div>
{/if}
{#if fileSchemas.length > 0}
<div class="accordion-item">
<h2 class="accordion-header" id="panelsStayOpen-headingFS">
<button class="accordion-button " class:collapsed={!filesIsActive} type="button" data-bs-toggle="collapse"
data-bs-target="#panelsStayOpen-collapseFS" aria-expanded={filesIsActive}
aria-controls="panelsStayOpen-collapseFS">
Filesystem
</button>
</h2>
<div id="panelsStayOpen-collapseFS" class="accordion-collapse collapse" class:show={filesIsActive}
aria-labelledby="panelsStayOpen-headingFS">
<div class="accordion-body">
<NavbarMenu
schemas={ fileSchemas}
schema={schema}
/>
</div>
</div>
</div>
{/if}
</div>
</div>
</div>
-16
View File
@@ -1,16 +0,0 @@
<script>
import {getContext} from "svelte";
const channel = getContext("channel");
export let schemas;
export let schema;
</script>
<div class="list-group list-group-flush">
{#each schemas as aschema}
<a class="list-group-item list-group-item-action" class:active={aschema.name === schema?.name}
aria-current="page"
href="{channel.lucentUrl}/content/{aschema.name}">{aschema.label}</a>
{/each}
</div>
+15 -9
View File
@@ -1,23 +1,29 @@
<script> <script>
import {clickOutside} from "../../helpers.js";
export let width = "300";
let dropdownMenu; let dropdownMenu;
export function hide(){ export let orientation = "left";
dropdownMenu.classList.remove("show")
export function open() {
dropdownMenu.classList.remove("hide")
} }
function handleClickOutside() {
dropdownMenu.classList.add("hide")
}
</script> </script>
<div class="dropdown">
<button <button
class="button dropdown-button"
class="btn btn-sm btn-outline-primary dropdown-toggle d-flex align-items-center"
type="button" type="button"
data-bs-toggle="dropdown" on:click={open}
data-bs-auto-close="outside"
aria-expanded="false" aria-expanded="false"
> >
<slot name="button">Dropdown</slot> <slot name="button">Dropdown</slot>
</button> </button>
<div bind:this={dropdownMenu} class="dropdown-menu" style="width:{width}px;"> <div bind:this={dropdownMenu} class="dropdown-menu hide orientation-{orientation}" use:clickOutside on:click_outside={handleClickOutside}>
<slot/> <slot/>
</div> </div>
</div>
+2
View File
@@ -125,6 +125,7 @@
role="presentation" role="presentation"
{stroke} {stroke}
{fill} {fill}
> >
{@html selectedIcon.path} {@html selectedIcon.path}
</svg> </svg>
@@ -132,5 +133,6 @@
<style> <style>
svg { svg {
vertical-align: text-top; vertical-align: text-top;
} }
</style> </style>
+2 -2
View File
@@ -46,8 +46,8 @@
} }
</script> </script>
<div class="wrapper-large transparent "> <div class="">
<div class="lx-card mb-4 {inModal ? 'mt-0' : 'mt-5'}"> <div class="{inModal ? 'mt-0' : 'mt-5'}">
<h3 class="header-normal mb-5 "> <h3 class="header-normal mb-5 ">
{schema.label} {schema.label}
</h3> </h3>
+1 -1
View File
@@ -31,7 +31,7 @@
</script> </script>
<div class="lx-table rounded"> <div class="table">
<table class=""> <table class="">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
+29 -38
View File
@@ -1,6 +1,7 @@
<script> <script>
import Icon from "../../common/Icon.svelte"; import Icon from "../../common/Icon.svelte";
import {createEventDispatcher} from "svelte"; import {createEventDispatcher} from "svelte";
import Dropdown from "../../common/Dropdown.svelte";
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let schema; export let schema;
@@ -42,90 +43,80 @@
} }
</script> </script>
<div class=" ">
<button <Dropdown>
class="btn btn-sm btn-outline-primary dropdown-toggle d-flex align-items-center" <div slot="button">
type="button"
data-bs-toggle="dropdown"
data-bs-auto-close="outside"
aria-expanded="false"
>
{#if sortParam.startsWith("-")} {#if sortParam.startsWith("-")}
<Icon icon="arrow-down-wide-short"/> <Icon icon="arrow-down-wide-short"/>
{:else} {:else}
<Icon icon="arrow-up-short-wide"/> <Icon icon="arrow-up-short-wide"/>
{/if} {/if}
<span class="ms-1">{sortField.label}</span> <span class="ms-1">{sortField.label}</span>
</button> </div>
<div class="dropdown-menu" style="width:auto;max-width:800px;"> <div>
<div class="row">
{#each sortableFields as field} {#each sortableFields as field}
<div class="col-4 px-3 py-1 d-flex align-items-center"> <div class="dropdown-item">
<div class="btn-group w-100">
<button <button
on:click={(e) => sortAsc(e, field)} on:click={(e) => sortAsc(e, field)}
title="Sort Ascending" title="Sort Ascending"
class="btn btn-sm {field.name == sortField.name && !sortParam.startsWith("-") class="button button-icon {field.name == sortField.name && !sortParam.startsWith("-")
? 'btn-primary' ? 'active'
: 'btn-outline-primary'} " : ''} "
> >
<Icon icon="arrow-up-short-wide"/> <Icon icon="arrow-up-short-wide"/>
</button> </button>
<button <button
on:click={(e) => sortDesc(e, field)} on:click={(e) => sortDesc(e, field)}
title="Sort Descending" title="Sort Descending"
class="btn btn-sm {field.name == sortField.name && sortParam.startsWith("-") class="button button-icon {field.name == sortField.name && sortParam.startsWith("-")
? 'btn-primary' ? 'active'
: 'btn-outline-primary'} " : ''} "
> >
<Icon icon="arrow-down-wide-short"/> <Icon icon="arrow-down-wide-short"/>
</button> </button>
<button <button
title="Sort Ascending" title="Sort Ascending"
on:click={(e) => sortAsc(e, field)} on:click={(e) => sortAsc(e, field)}
class="btn btn-sm btn-outline-primary w-100 text-nowrap" class="button"
style="overflow: hidden;"
> >
{field.label} {field.label}
</button> </button>
</div> </div>
</div>
{/each} {/each}
</div> <h6 class="dropdown-header">System</h6>
<h6 class="dropdown-header px-0">System</h6>
<div class="row">
{#each systemFieldsFiltered as field} {#each systemFieldsFiltered as field}
<div class="col-4 px-3 py-1 d-flex align-items-center"> <div class="dropdown-item">
<div class="btn-group w-100">
<button <button
on:click={(e) => sortAsc(e, field)} on:click={(e) => sortAsc(e, field)}
title="Sort Ascending" title="Sort Ascending"
class="btn btn-sm {field.name == sortParam class="button button-icon {field.name == sortParam
? 'btn-primary' ? 'active'
: 'btn-outline-primary'} " : ''} "
> >
<Icon icon="arrow-up-short-wide"/> <Icon icon="arrow-up-short-wide"/>
</button> </button>
<button <button
on:click={(e) => sortDesc(e, field)} on:click={(e) => sortDesc(e, field)}
title="Sort Descending" title="Sort Descending"
class="btn btn-sm {'-' + field.name == sortParam class="button button-icon {'-' + field.name == sortParam
? 'btn-primary' ? 'active'
: 'btn-outline-primary'} " : ''} "
> >
<Icon icon="arrow-down-wide-short"/> <Icon icon="arrow-down-wide-short"/>
</button> </button>
<button <button
title="Sort Ascending" title="Sort Ascending"
on:click={(e) => sortAsc(e, field)} on:click={(e) => sortAsc(e, field)}
class="btn btn-sm btn-outline-primary w-100 text-nowrap" class="button"
style="overflow: hidden;"
> >
{field.label} {field.label}
</button> </button>
</div> </div>
</div>
{/each} {/each}
</div> </div>
</div> </Dropdown>
</div>
+10 -23
View File
@@ -4,7 +4,8 @@
import Icon from "../../common/Icon.svelte"; import Icon from "../../common/Icon.svelte";
import SortFields from "./SortFields.svelte"; import SortFields from "./SortFields.svelte";
import AppliedFilter from "./AppliedFilter.svelte"; import AppliedFilter from "./AppliedFilter.svelte";
import {getContext, createEventDispatcher} from "svelte"; import {createEventDispatcher, getContext} from "svelte";
import Dropdown from "../../common/Dropdown.svelte";
const channel = getContext("channel"); const channel = getContext("channel");
@@ -47,8 +48,8 @@
} }
</script> </script>
<div class="mb-3 d-flex align-items-center justify-content-between"> <div class="toolbar">
<div class=" d-flex align-items-center"> <div class="toolbar-filters">
<SortFields <SortFields
{schema} {schema}
@@ -79,12 +80,12 @@
</div> </div>
<div class="d-flex align-items-center "> <div style="display:flex;align-items: center">
{#if schema.type === "collection"} {#if schema.type === "collection"}
{#if !inModal && isWritable} {#if !inModal && isWritable}
<a <a
href="{channel.lucentUrl}/records/new?schema={schema.name}" href="{channel.lucentUrl}/records/new?schema={schema.name}"
class="btn btn-sm btn-primary" class="button"
> >
New Record New Record
</a> </a>
@@ -95,48 +96,34 @@
</div> </div>
{/if} {/if}
{#if !inModal} {#if !inModal}
<div class="dropdown d-inline-block"> <Dropdown orientation="right">
<button <div slot="button">
class="btn btn-link btn-sm"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<Icon icon="ellipsis-vertical"/> <Icon icon="ellipsis-vertical"/>
</button> </div>
<ul class="dropdown-menu">
{#if filter["status_in"] === "trashed"} {#if filter["status_in"] === "trashed"}
{#if isWritable} {#if isWritable}
<li>
<a <a
class="dropdown-item" class="dropdown-item"
href="{channel.lucentUrl}/content/{schema.name}/emptyTrash" href="{channel.lucentUrl}/content/{schema.name}/emptyTrash"
> >
Empty trash Empty trash
</a> </a>
</li>
{/if} {/if}
{:else} {:else}
<li>
<a <a
class="dropdown-item" class="dropdown-item"
href={csvUrl} href={csvUrl}
>Export to CSV</a >Export to CSV</a
> >
</li>
<li>
<a <a
class="dropdown-item" class="dropdown-item"
href="{channel.lucentUrl}/content/{schema.name}?filter[status_in]=trashed" href="{channel.lucentUrl}/content/{schema.name}?filter[status_in]=trashed"
>View trashed records</a >View trashed records</a
> >
</li>
{/if} {/if}
</Dropdown>
</ul>
</div>
{/if} {/if}
</div> </div>
</div> </div>
+21 -4
View File
@@ -28,14 +28,14 @@
fontSize = "13"; fontSize = "13";
} }
</script> </script>
<div style="display: flex;align-items: center;gap: 5px;">
{#if record} {#if record}
{#if record._file.mime.startsWith("image")} {#if record._file.mime.startsWith("image")}
<!-- href={imgurl(record)} --> <!-- href={imgurl(record)} -->
<a <a
href="{channel.lucentUrl}/records/{record.id}" href="{channel.lucentUrl}/records/{record.id}"
title={record._file.path} title={record._file.path}
class="d-flex align-items-center justify-content-center "
style="width:{imageSide}px;height:{imageSide}px" style="width:{imageSide}px;height:{imageSide}px"
> >
<img <img
@@ -48,11 +48,11 @@
<a <a
href="{channel.lucentUrl}/records/{record.id}" href="{channel.lucentUrl}/records/{record.id}"
title={record._file.path} title={record._file.path}
class="btn btn-outline-primary btn-sm d-flex align-items-center justify-content-center" class="file-preview-small"
style="width:{imageSide}px;height:{imageSide}px" style="width:{imageSide}px;height:{imageSide}px"
> >
<Icon icon="file" width={fileSide} height={fileSide}/> <Icon icon="file" width={fileSide} height={fileSide}/>
<span class="ms-2" style="font-size:{fontSize}px" <span class="ms-2"
>.{record._file.path.split(".").pop()}</span >.{record._file.path.split(".").pop()}</span
> >
</a> </a>
@@ -66,3 +66,20 @@
>{record._file.path}</a >{record._file.path}</a
> >
{/if} {/if}
</div>
<style>
img{
border-radius: 12px;
padding: 4px;
}
.file-preview-small{
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
border-radius: 12px;
padding: 4px;
background: var(--background);
}
</style>
+2 -5
View File
@@ -21,12 +21,11 @@
}); });
</script> </script>
<div class="wrapper-normal transparent">
<h3 class="header-small mb-4 mt-5">Latest Content changes</h3> <h3 class="header-small mb-4 mt-5">Latest Content changes</h3>
{#if records.length > 0} {#if records.length > 0}
<div class="lx-card mb-4">
<div class="lx-table p-0"> <div class="table">
<table class=""> <table class="">
<tbody> <tbody>
{#each records as record (record.id)} {#each records as record (record.id)}
@@ -37,8 +36,6 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
{/if} {/if}
</div>
+9 -9
View File
@@ -1,7 +1,6 @@
<script> <script>
import {formatDistanceToNow, parseJSON} from "date-fns"; import {formatDistanceToNow, parseJSON} from "date-fns";
import Avatar from "../account/Avatar.svelte"; import Avatar from "../account/Avatar.svelte";
import Status from "../records/Status.svelte";
import {previewTitle} from "../records/Preview"; import {previewTitle} from "../records/Preview";
import Preview from "../files/Preview.svelte"; import Preview from "../files/Preview.svelte";
import {usernameById} from "../account/users"; import {usernameById} from "../account/users";
@@ -19,29 +18,30 @@
</script> </script>
<td> <td>
<div class="row-name">
{#if record.status === "draft"}
<span class="status">DRAFT</span>
{/if}
{#if schema.type === "files"} {#if schema.type === "files"}
<Preview {record} size="tiny"/> <Preview {record} size="tiny" showFilename={true}/>
{:else} {:else}
<a <a
href="{channel.lucentUrl}/records/{record.id}" href="{channel.lucentUrl}/records/{record.id}"
class="text-decoration-none text-dark d-block"
> >
{previewTitle(channel.schemas, record, graph)} {previewTitle(channel.schemas, record, graph)}
</a> </a>
{/if} {/if}
</div>
</td> </td>
<td><a <td><a
class="text-decoration-none lx-small-text"
href="{channel.lucentUrl}/content/{schema.name}">{schema.label}</a href="{channel.lucentUrl}/content/{schema.name}">{schema.label}</a
> >
</td> </td>
<td class="text-center">
<Status status={record.status}/>
</td>
<td> <td>
<div class="d-flex"> <div style="display: flex;gap: 14px">
<Avatar name={usernameById(users, record._sys.updatedBy)} side={24}/> <Avatar name={usernameById(users, record._sys.updatedBy)} side={24}/>
<div class="ms-2"> <div class="ms-2">
{frieldlyUpdatedAt} {frieldlyUpdatedAt}
+26
View File
@@ -0,0 +1,26 @@
<script>
import Avatar from "../account/Avatar.svelte";
import {getContext} from "svelte";
const channel = getContext("channel");
const user = getContext("user");
</script>
<div class="top-nav ">
<a class="top-nav-item" href="{channel.lucentUrl}/members">Members</a>
{#if channel.generateCommand}
<a href="{channel.lucentUrl}/build-report" class="top-nav-item">Build website</a>
{/if}
<!-- <div>-->
<!-- <form method="GET">-->
<!-- <input type="search" name="filter[search_regex]" placeholder="Search"-->
<!-- class="form-control" required/>-->
<!-- </form>-->
<!-- </div>-->
<a href="{channel.lucentUrl}/profile">
<Avatar side="28" name={user.name}/>
</a>
</div>
+42
View File
@@ -0,0 +1,42 @@
<script>
import NavbarMenu from "./NavbarMenu.svelte";
import {getContext} from "svelte";
import Avatar from "../account/Avatar.svelte";
export let schema;
const channel = getContext("channel");
const readableSchemas = getContext("readableSchemas");
const user = getContext("user");
const fileSchemas = readableSchemas.filter((sc) => sc.type === "files");
const otherSchemas = readableSchemas.filter((sc) => !sc.isEntry && sc.type === "collection");
</script>
<div class="sidebar-top">
<a class="logo" href="{channel.lucentUrl}">{channel.name}</a>
<a class="nav-item" href="{channel.lucentUrl}/profile">
<Avatar side="28" name={user.name}/>
</a>
</div>
<div class="sidebar">
<NavbarMenu
title="Content"
schemas={ readableSchemas.filter((sc) => sc.isEntry)}
schema={schema}
expanded={true}
/>
<NavbarMenu
title="Files"
schemas={ fileSchemas}
schema={schema}
/>
<NavbarMenu
title="Other"
schemas={ otherSchemas}
schema={schema}
/>
</div>
+34
View File
@@ -0,0 +1,34 @@
<script>
import {getContext} from "svelte";
import Icon from "../common/Icon.svelte";
const channel = getContext("channel");
export let schemas;
export let title;
export let schema;
export let expanded = false;
if(schemas.find(s => s.name === schema?.name)){
expanded = true;
}
function toggleExpand(){
expanded = !expanded;
}
</script>
<div class="sidebar-header" role="button" tabindex="0" on:click={toggleExpand}>
{title}
{#if expanded}
<Icon icon="circle-chevron-up"></Icon>
{:else}
<Icon icon="circle-chevron-down"></Icon>
{/if}
</div>
{#if expanded}
{#each schemas as aschema}
<a class="sidebar-item" class:active={aschema.name === schema?.name}
aria-current="page"
href="{channel.lucentUrl}/content/{aschema.name}">{aschema.label}</a>
{/each}
{/if}
+20
View File
@@ -0,0 +1,20 @@
.button{
border-radius: 12px;
background: var(--background);
padding: 3px 10px;
cursor: pointer;
filter: brightness(97%);
border: none;
font-size: 14px;
&:focus {
filter: brightness(94%);
}
&:hover {
filter: brightness(94%);
}
&.active {
filter: brightness(74%);
}
}
+60
View File
@@ -0,0 +1,60 @@
.dropdown {
position: relative;
}
.dropdown-button > div {
display: flex;
align-items: center;
gap: 3px;
}
.dropdown-menu {
display: flex;
flex-direction: column;
padding: 10px;
overflow: visible;
position: absolute;
border-radius: 12px;
z-index: 9;
background: var(--background);
filter: brightness(97%);
transition: 600ms;
flex-grow: 1;
&.orientation-right {
right: 0;
}
&.orientation-left {
left: 0;
}
min-width: max-content;
}
.dropdown-header, .dropdown-item {
display: flex;
align-items: center;
gap: 3px;
text-wrap: nowrap;
}
.dropdown-header {
padding: 10px;
}
.dropdown-item {
font-size: 14px;
padding: 3px 10px;
&:hover{
background: var(--background);
filter: brightness(97%);
border-radius: 12px;
}
.button-icon {
flex-shrink: 0;
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ input{
} }
input,textarea{ input,textarea{
background: var(--input-bg); background: var(--input-bg);
border: 1px solid $border-color; border: 1px solid var(--border-color);
border-radius: 5px; border-radius: 5px;
padding: 5px 7px; padding: 5px 7px;
font-size: 16px; font-size: 16px;
+4 -1
View File
@@ -29,7 +29,10 @@
.gap-5{gap: 20px} .gap-5{gap: 20px}
.hide{ .hide{
display: none; display: none!important;
}
.hidden{
visibility: hidden;
} }
.d-block{ .d-block{
+3 -1
View File
@@ -1,4 +1,6 @@
.sidebar { .sidebar-content{
min-width: 300px;
max-width: 400px;
} }
.main-content { .main-content {
+7 -7
View File
@@ -1,21 +1,21 @@
.notice { .notice {
background-color: $background; background-color: var(--background);
padding: 25px 14px 14px; padding: 25px 14px 14px;
margin: 2rem 0; margin: 2rem 0;
filter: brightness(1.03); filter: brightness(1.03);
position: relative; position: relative;
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
border: 3px solid $border-color; border: 3px solid var(--border-color);
} }
.notice .title { .notice .title {
content: "NOTE"; content: "NOTE";
position: absolute; position: absolute;
background: $background; background: var(--background);
min-width: 90px; min-width: 90px;
border: 3px solid $border-color; border: 3px solid var(--border-color);
color: $text; color: var(--text);
display: block; display: block;
text-align: center; text-align: center;
left: 14px; left: 14px;
@@ -25,8 +25,8 @@
} }
.notice.success{ .notice.success{
border-color: $success; border-color: var(--success);
& .title{ & .title{
border-color: $success; border-color: var(--success);
} }
} }
+57 -17
View File
@@ -1,49 +1,89 @@
.sidebar-top{
font-size: 18px;
padding: 20px 20px ;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--background);
filter: brightness(97%);
margin-bottom: 15px;
border-radius: 12px;
}
.sidebar { .sidebar {
border: 1px solid $border-color; border: 0px solid var(--border-color);
border-radius: 12px; border-radius: 12px;
min-height: 100vh;
font-size: 15px; font-size: 15px;
line-height: 28px; line-height: 28px;
min-width: 300px; padding: 20px;
max-width: 400px; background: var(--background);
background: $background; filter: brightness(97%);
filter: brightness(104%); display: flex;
flex-direction: column;
gap: 3px;
} }
.sidebar-header { .sidebar-header {
background: $background; display: flex;
cursor: pointer;
justify-content: space-between;
align-items: center;
background: var(--background);
font-size: 16px; font-size: 16px;
padding: 12px 12px 6px; padding: 3px 12px 6px;
color: $text; color: var(--text);
filter: brightness(94%); filter: brightness(94%);
border-bottom: 0px solid var(--border-color);
border-radius: 12px;
&:hover {
background: var(--secondary);
}
&:first-child { &:first-child {
}
&:last-child {
border-bottom: none; border-bottom: none;
border-radius: 12px 12px 0 0;
} }
} }
.sidebar-item { .sidebar-item {
color: $text; color: var(--text);
display: block; display: block;
font-size: 14px; font-size: 14px;
padding: 6px 12px; padding: 3px 12px;
text-decoration: none; text-decoration: none;
border-bottom: 1px solid $border-color; border-bottom: 0px solid var(--border-color);
transition: 600ms; transition: 600ms;
border-radius: 12px;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
border-radius: 0 0 12px 12px;
} }
&:hover { &:hover {
background: $secondary; background: var(--secondary);
} }
&.active { &.active {
background: $secondary; background: var(--secondary);
}
}
.top-nav{
display: flex;
justify-content: end;
align-items: center;
gap: 10px;
}
.top-nav-item{
border-radius: 12px;
font-size: 14px;
filter: brightness(97%);
background: var(--background);
padding: 3px 10px ;
&:hover {
background: var(--secondary);
} }
} }
+22 -5
View File
@@ -1,8 +1,12 @@
.lx-table { .table {
min-width: 600px; min-width: 600px;
overflow: auto; overflow: auto;
border-radius: 12px;
padding: 20px;
background: var(--background);
filter: brightness(97%);
table { table {
min-width: 600px; width: 100%;
} }
th { th {
@@ -13,7 +17,6 @@
// height: 34px; // height: 34px;
padding: 8px 16px; padding: 8px 16px;
// border-bottom: 1px solid #ccc; // border-bottom: 1px solid #ccc;
background: #eee;
&.is-sort { &.is-sort {
background-color: rgba($primary, 0.1); background-color: rgba($primary, 0.1);
} }
@@ -26,20 +29,34 @@
max-width: 400px; max-width: 400px;
height: 48px; height: 48px;
padding: 4px 16px; padding: 4px 16px;
overflow: hidden; overflow: hidden;
&.is-sort { &.is-sort {
background-color: rgba($primary, 0.1); background-color: rgba($primary, 0.1);
} }
img{
width: 48px;
}
.status{
color:var(--accent);
font-size: 80%;
}
.row-name{
display: flex;
align-items: center;
gap: 6px;
}
} }
tr { tr {
background-color: #fff;
&:hover { &:hover {
box-shadow: inset 0em 0em 0em 10em rgba(0, 0, 0, 0.1); box-shadow: inset 0em 0em 0em 10em rgba(0, 0, 0, 0.1);
} }
} }
tr:nth-child(odd) { tr:nth-child(odd) {
background-color: #f9f9f9; //background-color: #f9f9f9;
} }
td:nth-child(odd) { td:nth-child(odd) {
+9
View File
@@ -0,0 +1,9 @@
.toolbar{
display: flex;
align-items: center;
gap: 5px;
justify-content: space-between;
}
.toolbar-filters{ display: flex;
align-items: center;
gap: 5px;}
+5 -2
View File
@@ -116,10 +116,13 @@
} }
.header-normal { .header-normal {
text-align: center; text-align: left;
font-weight: 400;
font-size: 20px;
} }
.header-small { .header-small {
text-align: left; text-align: left;
font-size: 26px; font-weight: 400;
font-size: 20px;
} }
+28 -21
View File
@@ -90,9 +90,7 @@ $success: #80c671;
$background: #f4f6fa; $background: #f4f6fa;
$table-striped-bg-factor: 0.03; $table-striped-bg-factor: 0.03;
$dropdown-bg: rgb(206, 223, 210); $dropdown-bg: rgb(206, 223, 210);
$border-color: #000;
$text: #04060b;
$accent: #80c671;
//https://www.realtimecolors.com/?colors=04060b-f4f6fa-5b86be-d9cca1-80c671&fonts=Anek Telugu-Anek Telugu //https://www.realtimecolors.com/?colors=04060b-f4f6fa-5b86be-d9cca1-80c671&fonts=Anek Telugu-Anek Telugu
$themes: ( $themes: (
@@ -111,7 +109,25 @@ $themes: (
accent: #488e39, accent: #488e39,
), ),
); );
:root{
--linearPrimarySecondary: linear-gradient(#5b86be, #d9cca1);
--linearPrimaryAccent: linear-gradient(#5b86be, #80c671);
--linearSecondaryAccent: linear-gradient(#d9cca1, #80c671);
--radialPrimarySecondary: radial-gradient(#5b86be, #d9cca1);
--radialPrimaryAccent: radial-gradient(#5b86be, #80c671);
--radialSecondaryAccent: radial-gradient(#d9cca1, #80c671);
--border-color: #000;
--main-font: Open Sans, Arial, Helvetica, sans-serif;
--main-font-color: #444;
--input-bg: rgb(245,245,249);
--text: #010b05;
--background: #f7fefa;
--primary: #1ce776;
--secondary: #7bc8f1;
--accent: #5086ed;
--success: #80c671;
}
//@import "../node_modules/bootstrap/scss/bootstrap"; //@import "../node_modules/bootstrap/scss/bootstrap";
@@ -130,25 +146,17 @@ $themes: (
@import "./card"; @import "./card";
@import "./files"; @import "./files";
@import "./revisions"; @import "./revisions";
@import "./toolbar";
@import "./dropdown";
@import "./button";
:root{
--linearPrimarySecondary: linear-gradient(#5b86be, #d9cca1);
--linearPrimaryAccent: linear-gradient(#5b86be, #80c671);
--linearSecondaryAccent: linear-gradient(#d9cca1, #80c671);
--radialPrimarySecondary: radial-gradient(#5b86be, #d9cca1);
--radialPrimaryAccent: radial-gradient(#5b86be, #80c671);
--radialSecondaryAccent: radial-gradient(#d9cca1, #80c671);
--border-color: $border-color;
--main-font: Open Sans, Arial, Helvetica, sans-serif;
--main-font-color: #444;
--input-bg: rgb(245,245,249);
}
body { body {
background-color: $background; background-color: var(--background);
font-family: var(--main-font), sans-serif;
} }
.btn-spinner .spinner-border { .btn-spinner .spinner-border {
@@ -168,9 +176,8 @@ body {
border-color: transparent; border-color: transparent;
} }
.dropdown-menu {
border: 0; a{
border-radius: 15px; color: var(--text);
box-shadow: 0 0 4px #ccc; text-decoration: none;
padding: 30px 15px;
} }
+1 -1
View File
@@ -1,5 +1,5 @@
<div class="d-flex align-items-center "> <div class="d-flex align-items-center ">
<a class="nav-item" href="/lucent">{{$channel->name}}</a>
<a class="nav-item" href="{channel.lucentUrl}/members">Members</a> <a class="nav-item" href="{channel.lucentUrl}/members">Members</a>
@if($channel->generateCommand) @if($channel->generateCommand)
+4 -6
View File
@@ -23,13 +23,11 @@
</head> </head>
<body> <body>
@include("lucent::includes.header")
<div class="main-wrapper">
@include("lucent::sidebar.sidebar")
<div class="main-content">
@yield('content') @yield('content')
</div>
</div>
</body> </body>
</html> </html>
+4 -4
View File
@@ -2,9 +2,9 @@
$schema = $schemas->where("name",$record->schema)->first(); $schema = $schemas->where("name",$record->schema)->first();
@endphp @endphp
<td> <td>
{{-- {#if schema.type === "files"}--}} @if($schema->type === "files")
{{-- <Preview {record} size="tiny"/>--}} <Preview {record} size="tiny"/>
{{-- {:else}--}} @else
<a <a
href="/lucent/records/{{$record->id}}" href="/lucent/records/{{$record->id}}"
class="text-decoration-none text-dark d-block" class="text-decoration-none text-dark d-block"
@@ -13,7 +13,7 @@
</a> </a>
{{$record->status->value === "draft" ? "Draft" : ""}} {{$record->status->value === "draft" ? "Draft" : ""}}
{{-- {/if}--}} @endif
</td> </td>
<td><a <td><a
+2
View File
@@ -1,4 +1,6 @@
<a class="nav-item" href="/lucent">{{$channel->name}}</a>
<div class="sidebar"> <div class="sidebar">
<div class="sidebar-header"> <div class="sidebar-header">
Content Content
</div> </div>
+7 -29
View File
@@ -21,36 +21,14 @@ class HomeController extends Controller
{ {
} }
public function home(Request $request): View public function home(): View
{ {
$urlParams = $request->all();
$users = $this->accountService->all();
$sort = data_get($urlParams, "sort") ?? "-_sys.updatedAt";
$filter = data_get($urlParams, "filter") ?? [];
$arguments = array_merge([
"schema_in" => $this->accountService->currentReadableSchemas(),
"status_in" => ["draft", "published"]
], $filter);
$limit = 10;
$graph = $this->query
->filter($arguments)
->limit($limit)
->childrenDepth(1)
->parentsDepth(0)
->sort($sort)
->run();
return view("lucent::home", [
"users" => $users,
"records" => $graph->getRootRecords(),
"graph" => toArray($graph),
"modalUrl" => $request->fullUrl(),
]);
return $this->svelte->render(
layout: "channel",
view: "homeIndex",
title: "Records",
);
} }
public function records(Request $request): Response public function records(Request $request): Response
@@ -65,7 +43,7 @@ class HomeController extends Controller
"status_in" => ["draft", "published"] "status_in" => ["draft", "published"]
], $filter); ], $filter);
$limit = 30; $limit = 20;
$graph = $this->query $graph = $this->query
->filter($arguments) ->filter($arguments)