Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dfe4576725 | |||
| fea7610665 | |||
| 828fca7e8f | |||
| 065b121e10 | |||
| f949852c1a | |||
| 986d3420cb | |||
| e9537862ca | |||
| fda4bced92 | |||
| c3e6f9ff64 | |||
| b208e79d15 | |||
| 19e8d648fc | |||
| 800e2746e0 | |||
| bb27811ddf | |||
| 52a1ec5c5a | |||
| 07b72b0a2c | |||
| 4ef16f3630 | |||
| e06e1db671 | |||
| 174a119c2e | |||
| 55db377abf | |||
| cebe24ea67 | |||
| b729df6923 | |||
| 843f560710 | |||
| 7574d67d80 | |||
| 19931cb4d1 | |||
| 6458c1e71d | |||
| 63232585ab | |||
| 6d15591601 | |||
| 32c8378020 | |||
| d0cd8228cc | |||
| c45a3847f8 | |||
| c0b3878674 | |||
| f868219981 | |||
| 8ac0567e66 | |||
| 02f8f5970a | |||
| 0cd4e08716 | |||
| cf3d621587 | |||
| 6fc0a65b6f | |||
| a73ee21568 | |||
| ff54bcc2ef | |||
| ab1517cc8f | |||
| 9f724a3243 | |||
| ae65ca47f6 | |||
| 74d2fcc4fa | |||
| 82174afdea | |||
| ffc39f078d | |||
| 7c4e19afbc | |||
| 7b10bfca1d | |||
| 0e5ac08641 | |||
| 1505aaa909 | |||
| d9e2c4954a | |||
| 97ad9de3d2 | |||
| 9e140be0ec | |||
| a737c2d571 | |||
| c43c29eb14 |
@@ -9,8 +9,8 @@ include_toc: true
|
||||
|
||||
### Requirements
|
||||
|
||||
- PHP 8.2
|
||||
- Laravel 10
|
||||
- PHP 8.3
|
||||
- Laravel 11
|
||||
- Postgres or Sqlite database
|
||||
- ImageMagick
|
||||
|
||||
@@ -82,7 +82,9 @@ return [
|
||||
### Database
|
||||
|
||||
The recommended database for small website is sqlite. But you can also use postresql
|
||||
Make sure to delete the existing migration scripts in your database/migrations folder.
|
||||
|
||||
> [!CAUTION]
|
||||
> Make sure to delete the existing migration scripts in your database/migrations folder.
|
||||
|
||||
Then run:
|
||||
|
||||
@@ -90,6 +92,26 @@ Then run:
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
### File Storage
|
||||
|
||||
You can use your local filesystem or s3 compatible storage. Lucent expects you to have a valid configuration inside ``config/filesystems.php``
|
||||
|
||||
example:
|
||||
|
||||
```php
|
||||
return [
|
||||
'disks' => [
|
||||
'lucent' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'public',
|
||||
'throw' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
### First user
|
||||
|
||||
To create your first user, head to your localhost:8000/lucent
|
||||
|
||||
+6
-7
@@ -8,18 +8,17 @@
|
||||
"ext-zip": "*",
|
||||
"ext-sqlite3": "*",
|
||||
"ext-imagick": "*",
|
||||
"ext-pdo": "*",
|
||||
"php": "^8.3",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"intervention/image": "^2.7",
|
||||
"phpoption/phpoption": "^1.9",
|
||||
"spatie/image-optimizer": "^1.6",
|
||||
"staudenmeir/laravel-cte": "^1.0",
|
||||
"ext-pdo": "*",
|
||||
"mustache/mustache": "^2.14"
|
||||
"staudenmeir/laravel-cte": "^1.10",
|
||||
"intervention/image": "^3.8",
|
||||
"guzzlehttp/guzzle": "^7.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"laravel/framework": "^10.10"
|
||||
"laravel/framework": "^10.48",
|
||||
"phpstan/phpstan": "^1.12"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+287
-351
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
"env" => env("LUCENT_ENV", "production"),
|
||||
"schemas_path" => env("LUCENT_SCHEMAS_PATH", "resources/lucent/schemas"),
|
||||
"image_filters_path" => "app/Filters",
|
||||
"database" => env('LUCENT_DB_CONNECTION', env('DB_CONNECTION', "sqlite")),
|
||||
"name" => env("LUCENT_NAME", "Stoic"),
|
||||
"url" => env("LUCENT_URL", env('APP_URL')),
|
||||
"preview_target" => env("LUCENT_PREVIEW_TARGET", "previewTarget"),
|
||||
/*
|
||||
* Make available laravel artisan commands for admin users
|
||||
* example:
|
||||
* [
|
||||
* "command1:signature" => "Description 1"
|
||||
* "command2:signature" => "Description 2"
|
||||
* ]
|
||||
*
|
||||
* */
|
||||
"commands" => [],
|
||||
"can_invite" => ["admin"],
|
||||
"can_run_commands" => ["admin"],
|
||||
"system_user_id" => ""
|
||||
];
|
||||
+5
-11
@@ -24,7 +24,8 @@ There are 3 types of schemas
|
||||
- **fields**: The list of your fields. Look the field reference for more
|
||||
- **isEntry**: If this schema is important, it will show be visible on the main the sidebar. Default: false _optional_
|
||||
- **sortBy**: The default sorting in the content browser _optional_
|
||||
- **titleTemplate**: Mustache code to customize the preview field _optional_
|
||||
- **cardTitle**: Mustache code to customize the preview field _optional_
|
||||
- **cardImage**: Field name of image you want to use as a preview image _optional_
|
||||
- **revisions**: How many revisions are going to be kept for each record _optional_
|
||||
- **read**: Array of user groups that have read permissions _optional_
|
||||
- **write**: Array of user groups that have write permissions _optional_
|
||||
@@ -40,20 +41,12 @@ There are 3 types of schemas
|
||||
- **fields**: The list of your fields. Look the field reference for more
|
||||
- **isEntry**: If this schema is important, it will show be visible on the main the sidebar _optional_
|
||||
- **sortBy**: The default sorting in the content browser _optional_
|
||||
- **titleTemplate**: Mustache code to customize the preview field _optional_
|
||||
- **cardTitle**: Mustache code to customize the preview field _optional_
|
||||
- **revisions**: How many revisions are going to be kept for each record _optional_
|
||||
- **read**: Array of user groups that have read permissions _optional_
|
||||
- **write**: Array of user groups that have write permissions _optional_
|
||||
|
||||
|
||||
## Block Reference
|
||||
|
||||
- **name**: The ID of the collection. Camelcase and plural is the recommended format ex. blogPosts
|
||||
- **label**: The friendly name of the schema
|
||||
- **type**: The type of the collection. Should be "block"
|
||||
- **fields**: The list of your fields. Look the field reference for more
|
||||
|
||||
|
||||
A full Collection example without the fields:
|
||||
|
||||
```json
|
||||
@@ -74,7 +67,8 @@ A full Collection example without the fields:
|
||||
"SEO"
|
||||
],
|
||||
"sortBy": "-_sys.createdAt",
|
||||
"titleTemplate": "{{name}} {{slug}}",
|
||||
"schemaTitle": "{{name}} {{slug}}",
|
||||
"schemaImage": "cover",
|
||||
"revisions": 15,
|
||||
"read": [
|
||||
"admin",
|
||||
|
||||
Vendored
-198
File diff suppressed because one or more lines are too long
Vendored
+225
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"main.js": {
|
||||
"file": "assets/main-0h36XLim.js",
|
||||
"file": "assets/main-C4XTQmaY.js",
|
||||
"name": "main",
|
||||
"src": "main.js",
|
||||
"isEntry": true,
|
||||
"css": [
|
||||
"assets/main-CaexgiEy.css"
|
||||
"assets/main-BJijircB.css"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export function debounce(callback, wait) {
|
||||
let timeoutId = null;
|
||||
|
||||
return (...args) => {
|
||||
window.clearTimeout(timeoutId);
|
||||
|
||||
timeoutId = window.setTimeout(() => {
|
||||
callback.apply(null, args);
|
||||
}, wait);
|
||||
};
|
||||
}
|
||||
+19
-3
@@ -1,18 +1,18 @@
|
||||
import {formatDistanceToNow, parseJSON, format, parse} from "date-fns";
|
||||
import {format, formatDistanceToNow, parseJSON} from "date-fns";
|
||||
|
||||
export function friendlyDate(date) {
|
||||
return formatDistanceToNow(parseJSON(date), {addSuffix: true});
|
||||
}
|
||||
|
||||
export function readableDate(date) {
|
||||
if(!date){
|
||||
if (!date) {
|
||||
return "";
|
||||
}
|
||||
return format(parseJSON(date), "dd MMM yyyy");
|
||||
}
|
||||
|
||||
export function readableDatetime(date) {
|
||||
if(!date){
|
||||
if (!date) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -50,3 +50,19 @@ export function clickOutside(node) {
|
||||
}
|
||||
}
|
||||
|
||||
export function uniqueBy(list, callback) {
|
||||
const itemMap = list.reduce((c, item) => {
|
||||
c[callback(item)] = item;
|
||||
return c;
|
||||
}, {});
|
||||
|
||||
return Object.values(itemMap);
|
||||
}
|
||||
|
||||
export function range(start, end) {
|
||||
var ans = [];
|
||||
for (let i = start; i <= end; i++) {
|
||||
ans.push(i);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {axiosInstance} from "./bootstrap";
|
||||
import "../sass/app.scss";
|
||||
import Account from "./svelte/Account.svelte";
|
||||
import Channel from "./svelte/Channel.svelte";
|
||||
import Mustache from "mustache";
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
setContext("user", user);
|
||||
</script>
|
||||
<div style="text-align: center;background: var(--p20);padding: 20px;color: var(--p90)">
|
||||
<h1><a class="text-decoration-none" href="{channel.lucentUrl}">{channel.name}</a></h1>
|
||||
<h1><a class="text-decoration-none" href="{channel.lucentUrl}">{channel.name ?? "Lucent Setup"}</a></h1>
|
||||
</div>
|
||||
<div>
|
||||
<svelte:component this={components[view]} {title} {...data}/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import SpinnerButton from "../common/SpinnerButton.svelte";
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
let email = "";
|
||||
@@ -14,7 +15,6 @@
|
||||
email: email,
|
||||
})
|
||||
.then((response) => {
|
||||
console.log(response)
|
||||
message = "You will receive an email with a login link"
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import Avatar from "./Avatar.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import SuccessAlert from "../common/SuccessAlert.svelte";
|
||||
import axios from "axios";
|
||||
|
||||
const user = getContext("user");
|
||||
const channel = getContext("channel");
|
||||
@@ -25,7 +26,6 @@
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data.error;
|
||||
console.log({errorMessage});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data.error;
|
||||
console.log({errorMessage});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
<script>
|
||||
import {getContext, onMount} from "svelte";
|
||||
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let title;
|
||||
export let command;
|
||||
$: date = "";
|
||||
$: logs = "";
|
||||
|
||||
let anchorEl;
|
||||
let inProgress = false;
|
||||
|
||||
function connect() {
|
||||
const eventSource = new EventSource(channel.lucentUrl + "/build-report-source");
|
||||
const eventSource = new EventSource(channel.lucentUrl + "/command-report-source/" + command.signature );
|
||||
|
||||
eventSource.onmessage = function (event) {
|
||||
inProgress = true;
|
||||
const data = JSON.parse(event.data);
|
||||
date = data.date;
|
||||
logs = data.logs;
|
||||
|
||||
anchorEl.scrollIntoView()
|
||||
}
|
||||
eventSource.onerror = (e) => {
|
||||
console.log(e)
|
||||
eventSource.close();
|
||||
inProgress = false;
|
||||
}
|
||||
@@ -28,8 +30,7 @@
|
||||
function buildWebsite(e) {
|
||||
e.preventDefault();
|
||||
inProgress = true;
|
||||
|
||||
axios.post(channel.lucentUrl + "/build").then(response => {
|
||||
axios.post(channel.lucentUrl + "/command/" + command.signature).then(response => {
|
||||
connect()
|
||||
})
|
||||
|
||||
@@ -46,26 +47,36 @@
|
||||
|
||||
<h3 class="header-small mb-5">{title}</h3>
|
||||
|
||||
<button on:click={buildWebsite} class="button primary mb-3" disabled={inProgress}>Start Build
|
||||
<button on:click={buildWebsite} class="button primary mb-3" disabled={inProgress}>Start
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
{#if inProgress}
|
||||
<span class="badge text-bg-warning">
|
||||
Build in progress
|
||||
Action in progress
|
||||
</span>
|
||||
{/if}
|
||||
{#if !inProgress && logs}
|
||||
<span class="badge text-bg-info">
|
||||
Build completed
|
||||
Action completed
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<pre>{logs}</pre>
|
||||
<pre class="logs">{logs}
|
||||
<div bind:this={anchorEl}> </div>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.logs{
|
||||
max-height: 70vh;
|
||||
overflow: scroll;
|
||||
background: var(--p90);
|
||||
color: var(--p10);
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -113,6 +113,26 @@
|
||||
path: '<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12l4-4m-4 4 4 4"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
},
|
||||
"list": {
|
||||
path: '<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M9 8h10M9 12h10M9 16h10M4.99 8H5m-.02 4h.01m0 4H5"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
},
|
||||
"ordered-list": {
|
||||
path: '<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6h8m-8 6h8m-8 6h8M4 16a2 2 0 1 1 3.321 1.5L4 20h5M4 5l2-1v6m-2 0h4"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
},
|
||||
"italic": {
|
||||
path: '<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m8.874 19 6.143-14M6 19h6.33m-.66-14H18"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
},
|
||||
"undo": {
|
||||
path: '<path fill-rule="evenodd" clip-rule="evenodd" d="M7.53033 3.46967C7.82322 3.76256 7.82322 4.23744 7.53033 4.53033L5.81066 6.25H15C18.1756 6.25 20.75 8.82436 20.75 12C20.75 15.1756 18.1756 17.75 15 17.75H8.00001C7.58579 17.75 7.25001 17.4142 7.25001 17C7.25001 16.5858 7.58579 16.25 8.00001 16.25H15C17.3472 16.25 19.25 14.3472 19.25 12C19.25 9.65279 17.3472 7.75 15 7.75H5.81066L7.53033 9.46967C7.82322 9.76256 7.82322 10.2374 7.53033 10.5303C7.23744 10.8232 6.76256 10.8232 6.46967 10.5303L3.46967 7.53033C3.17678 7.23744 3.17678 6.76256 3.46967 6.46967L6.46967 3.46967C6.76256 3.17678 7.23744 3.17678 7.53033 3.46967Z" fill="#1C274C"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
},
|
||||
"destroy": {
|
||||
path: '<path d="M17 7L15 9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/><path d="M19.5 7.5L20.5 8" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/><path d="M16 3.5L16.5 4.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/><path d="M19 5L20 4" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/><path\n'+' d="M5.75 8.00337C6.85315 7.36523 8.13392 7 9.5 7C13.6421 7 17 10.3579 17 14.5C17 18.6421 13.6421 22 9.5 22C5.35786 22 2 18.6421 2 14.5C2 13.1339 2.36523 11.8532 3.00337 10.75" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>',
|
||||
viewBox: "0 0 24 24",
|
||||
}
|
||||
};
|
||||
|
||||
export let width = 16;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let selected;
|
||||
@@ -16,7 +17,7 @@
|
||||
window.location.reload();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,13 +25,13 @@
|
||||
axios
|
||||
.post(channel.lucentUrl + "/records/status/" + status, {
|
||||
schemaName: schema.name,
|
||||
records: selected
|
||||
records: selected.map((s) => s.id),
|
||||
})
|
||||
.then((response) => {
|
||||
window.location.reload();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -50,20 +51,6 @@
|
||||
</button
|
||||
>
|
||||
{#if filter["status_in"] === "trashed"}
|
||||
<button
|
||||
on:click|preventDefault={(e) => changeStatus(e, "published")}
|
||||
type="button"
|
||||
class="button">Publish
|
||||
</button
|
||||
>
|
||||
{#if schema.hasDrafts}
|
||||
<button
|
||||
on:click|preventDefault={(e) => changeStatus(e, "draft")}
|
||||
type="button"
|
||||
class="button">Make Draft
|
||||
</button
|
||||
>
|
||||
{/if}
|
||||
<button
|
||||
on:click|preventDefault={deleteRecords}
|
||||
type="button"
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
import Number from "./elements/Number.svelte";
|
||||
|
||||
import Text from "./elements/Text.svelte";
|
||||
import Url from "./elements/Url.svelte";
|
||||
import Date from "./elements/Date.svelte";
|
||||
import Datetime from "./elements/Datetime.svelte";
|
||||
import File from "./elements/File.svelte";
|
||||
import Uuid from "./elements/UUID.svelte";
|
||||
import Rich from "./elements/Rich.svelte";
|
||||
|
||||
const renderElements = {
|
||||
@@ -22,10 +20,8 @@
|
||||
checkbox: Checkbox,
|
||||
reference: Reference,
|
||||
number: Number,
|
||||
url: Url,
|
||||
date: Date,
|
||||
datetime: Datetime,
|
||||
uuid: Uuid,
|
||||
file: File,
|
||||
};
|
||||
export let field;
|
||||
|
||||
@@ -83,7 +83,11 @@
|
||||
{#if record._file?.path}
|
||||
<div class="file-table-row">
|
||||
<Preview record={record} size={record._file?.width > 0 ? "medium" : "small"}/>
|
||||
|
||||
<div>
|
||||
{#if record.status === "draft"}
|
||||
<span style="text-transform: uppercase;font-size:10px">{record.status}</span>
|
||||
{/if}
|
||||
<a
|
||||
href="{channel.lucentUrl}/records/{record.id}"
|
||||
target={inModal ? "_blank" : "_self"}
|
||||
@@ -109,6 +113,9 @@
|
||||
href="{channel.lucentUrl}/records/{record.id}"
|
||||
target={inModal ? "_blank" : "_self"}
|
||||
>
|
||||
{#if record.status === "draft"}
|
||||
<span style="text-transform: uppercase;font-size:10px">{record.status}</span>
|
||||
{/if}
|
||||
{previewTitle(channel.schemas, record, graph)}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<div class="references">
|
||||
{#each recordEdges as recordEdge}
|
||||
<span class="mr-3">
|
||||
<span class="reference">
|
||||
<PreviewCardSmall {schemas} {graph} record={recordEdge}/>
|
||||
</span>
|
||||
{/each}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<script>
|
||||
export let value;
|
||||
</script>
|
||||
<span
|
||||
class="badge rounded-pill bg-primary bg-opacity-75"
|
||||
style="max-width:64px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;"
|
||||
title={value}
|
||||
data-bs-toggle="tooltip"
|
||||
>{value}</span
|
||||
>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script>
|
||||
export let value;
|
||||
</script>
|
||||
|
||||
<a href={value} target="_blank">{value}</a>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
import { range } from "lodash";
|
||||
import { range } from "../../../helpers.js";
|
||||
import NavItem from "./NavItem.svelte";
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
export let graph;
|
||||
|
||||
let filter = {
|
||||
label: "",
|
||||
operator: "",
|
||||
@@ -58,6 +57,7 @@
|
||||
const filterRecord = extractFilterRecord(graph, value);
|
||||
|
||||
function extractFilterRecord(graph, value) {
|
||||
|
||||
if (!filter.isReference) {
|
||||
return null;
|
||||
}
|
||||
@@ -82,7 +82,7 @@
|
||||
{#if filter.isReference && filterRecord}
|
||||
{filter.label} is {previewTitle(channel.schemas, filterRecord)}
|
||||
{:else}
|
||||
{filter.label} {operators.find((o) => o.name === filter.operator)?.symbol ?? ""} {value}
|
||||
{filter.label} {operators.find((o) => o.name === filter.operator)?.symbol ?? ""} {operators.find((o) => o.name === filter.operator)?.hasValue ? value : ""}
|
||||
{/if}
|
||||
|
||||
<button
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
|
||||
|
||||
let dropdown;
|
||||
let search = "";
|
||||
let systemFieldsFiltered = systemFields;
|
||||
@@ -70,6 +69,13 @@
|
||||
activeOperator = operators.find(o => o.name === "eq")
|
||||
}
|
||||
|
||||
function selectOperator(e, operator) {
|
||||
activeOperator = operator;
|
||||
if (!operator.hasValue) {
|
||||
applyFilter(e)
|
||||
}
|
||||
}
|
||||
|
||||
function applyFilter(e) {
|
||||
e.preventDefault();
|
||||
let filterPrefix = "";
|
||||
@@ -146,7 +152,7 @@
|
||||
<div class="selected-filter">field: {activeField.label}</div>
|
||||
|
||||
{#each activeOperators as operator}
|
||||
<button class="dropdown-item button" on:click={e => activeOperator = operator }>
|
||||
<button class="dropdown-item button" on:click={e => selectOperator(e,operator)}>
|
||||
{operator.label}
|
||||
</button>
|
||||
{/each}
|
||||
@@ -214,8 +220,8 @@
|
||||
required
|
||||
/>
|
||||
|
||||
<button class="button applied-filter">
|
||||
Submit
|
||||
<button class="button applied-filter">
|
||||
Submit
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import {createEventDispatcher, getContext} from "svelte";
|
||||
import {debounce} from "lodash";
|
||||
import {debounce} from "../../../debounce.js";
|
||||
import {previewTitle} from "../../records/Preview";
|
||||
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -5,7 +5,7 @@ export function sortByField(from, to, edges, fieldName, references) {
|
||||
if (from === to) {
|
||||
return edges;
|
||||
}
|
||||
let referenceIds = references.map(r => r.id);
|
||||
let referenceIds = references.map(r => r.record.id);
|
||||
let edgesTosort = edges?.filter((ed) => ed.field === fieldName && ed.depth === 1 && referenceIds.includes(ed.target)) ?? [];
|
||||
let remainingEdge = edges?.filter((ed) => !(ed.field === fieldName && ed.depth === 1)) ?? [];
|
||||
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
|
||||
export function imgurl(channel,record) {
|
||||
|
||||
export function imgurl(channel, record) {
|
||||
if (record._file.mime === "image/svg+xml") {
|
||||
return fileurl(channel, record);
|
||||
}
|
||||
return channel.filesUrl + `/thumbs/${record._file.path}`;
|
||||
const pathAr = record._file.path.split("/");
|
||||
return channel.disks[record._file.disk] + `/${pathAr[0]}/thumbs/${pathAr[1]}`;
|
||||
}
|
||||
|
||||
export function fileurl(channel, record) {
|
||||
return channel.filesUrl + `/${record._file.path}`;
|
||||
return channel.disks[record._file.disk] + `/${record._file.path}`;
|
||||
}
|
||||
|
||||
export function htmlurl(channel,record, preset) {
|
||||
export function htmlurl(channel, record, preset) {
|
||||
|
||||
let html = "";
|
||||
let url = fileurl(channel,record)
|
||||
let url = fileurl(channel, record)
|
||||
|
||||
if (record._file.width > 0) {
|
||||
let presetUrl = url;
|
||||
if (preset) {
|
||||
presetUrl = channel.filesUrl + `/templates/${preset}/${record._file.path}`;
|
||||
const pathAr = record._file.path.split("/");
|
||||
presetUrl = channel.disks[record._file.disk] + `/${pathAr[0]}/templates/${preset}/${pathAr[1]}`;
|
||||
}
|
||||
|
||||
html = `<img src="${presetUrl}" alt="${record._file.path}" />`
|
||||
} else if (record._file.mime === "image/svg+xml") {
|
||||
html = `<img src="${url}" alt="${record._file.path}"/>`
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import Icon from "../common/Icon.svelte";
|
||||
import Folder from "./Folder.svelte";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let folder;
|
||||
export let schema;
|
||||
export let expanded = folder.shouldExpand;
|
||||
|
||||
function toggleExpand() {
|
||||
expanded = !expanded;
|
||||
}
|
||||
</script>
|
||||
<div class="sidebar-folder">
|
||||
{#if folder.name !== ""}
|
||||
<button class="sidebar-header" tabindex="0" on:click={toggleExpand}>
|
||||
{folder.name.replaceAll("_", " ") ?? "Main"}
|
||||
{#if expanded}
|
||||
<Icon icon="circle-chevron-up"></Icon>
|
||||
{:else}
|
||||
<Icon icon="circle-chevron-down"></Icon>
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
{#if expanded}
|
||||
{#each folder.folders as aFolder}
|
||||
<Folder folder={aFolder} schema={schema}></Folder>
|
||||
{/each}
|
||||
|
||||
{#each folder.files 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}
|
||||
</div>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import Avatar from "../account/Avatar.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import Dropdown from "../common/Dropdown.svelte";
|
||||
|
||||
const channel = getContext("channel");
|
||||
const user = getContext("user");
|
||||
@@ -10,17 +11,18 @@
|
||||
<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 channel.commands.length > 0}
|
||||
<Dropdown>
|
||||
<div slot="button">Actions</div>
|
||||
{#each channel.commands as command}
|
||||
<a href="{channel.lucentUrl}/command-report/{command.signature}" class="top-nav-item">{command.name}</a>
|
||||
{/each}
|
||||
</Dropdown>
|
||||
|
||||
{/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>
|
||||
|
||||
<a href="{channel.lucentUrl}/profile">
|
||||
<Avatar side="28" name={user.name}/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,14 +1,39 @@
|
||||
<script>
|
||||
import NavbarMenu from "./NavbarMenu.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import Folder from "./Folder.svelte";
|
||||
|
||||
export let schema;
|
||||
const channel = getContext("channel");
|
||||
const readableSchemas = getContext("readableSchemas");
|
||||
|
||||
const fileSchemas = readableSchemas.filter((sc) => sc.type === "files");
|
||||
const otherSchemas = readableSchemas.filter((sc) => !sc.isEntry && sc.type === "collection");
|
||||
function addToFolder(tree, folderPath, aSchema) {
|
||||
let shouldExpand = aSchema.name === schema?.name;
|
||||
if (folderPath === "") {
|
||||
tree.files.push(aSchema)
|
||||
return tree
|
||||
}
|
||||
const folderNames = folderPath.split(".");
|
||||
folderNames.forEach(folderName => {
|
||||
let queriedFolder = tree.folders.find(folder => folder.name === folderName)
|
||||
if (!queriedFolder) {
|
||||
queriedFolder = {name: folderName, files: [], folders: [], shouldExpand: shouldExpand};
|
||||
}
|
||||
folderNames.shift()
|
||||
let remainingFolderPath = folderNames.join(".");
|
||||
queriedFolder = addToFolder(queriedFolder, remainingFolderPath, aSchema)
|
||||
|
||||
tree.folders = tree.folders.filter(f => f.name !== queriedFolder.name)
|
||||
tree.folders.push(queriedFolder);
|
||||
|
||||
})
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
const schemaTree = readableSchemas.reduce((carry, schema) => {
|
||||
carry = addToFolder(carry, schema.folder,schema)
|
||||
return carry;
|
||||
}, {name: "", files: [], folders: [], shouldExpand:true});
|
||||
</script>
|
||||
<div class="sidebar-top">
|
||||
<a class="logo" href="{channel.lucentUrl}">{channel.name}</a>
|
||||
@@ -16,24 +41,5 @@
|
||||
</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}
|
||||
/>
|
||||
<Folder folder={schemaTree} {schema} ></Folder>
|
||||
</div>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<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>
|
||||
|
||||
<button class="sidebar-header" tabindex="0" on:click={toggleExpand}>
|
||||
{title}
|
||||
{#if expanded}
|
||||
<Icon icon="circle-chevron-up"></Icon>
|
||||
{:else}
|
||||
<Icon icon="circle-chevron-down"></Icon>
|
||||
{/if}
|
||||
</button>
|
||||
{#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}
|
||||
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
|
||||
// https://codesandbox.io/s/codemirror-remark-editor-4m4z9?file=/src/CodeEditor.js:374-387
|
||||
import {onMount, onDestroy} from "svelte";
|
||||
import {onDestroy, onMount} from "svelte";
|
||||
import {basicSetup, EditorView} from "codemirror";
|
||||
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
||||
import {EditorState, Compartment} from "@codemirror/state";
|
||||
import {autocompletion, completionKeymap} from "@codemirror/autocomplete";
|
||||
import {Compartment, EditorState} from "@codemirror/state";
|
||||
import {keymap} from "@codemirror/view";
|
||||
import {indentWithTab} from "@codemirror/commands";
|
||||
import {markdown} from "@codemirror/lang-markdown";
|
||||
@@ -15,6 +15,29 @@
|
||||
export let value;
|
||||
export let editable = true;
|
||||
|
||||
export function insertMedia(info) {
|
||||
let insertText = "";
|
||||
if (info.record._file.width > 0) {
|
||||
insertText = ``;
|
||||
} else {
|
||||
insertText = `[${info.record._file.originalName}](${info.originalUrl})`;
|
||||
}
|
||||
const cursor = codeMirrorView.state.selection.main.head;
|
||||
const transaction = codeMirrorView.state.update({
|
||||
changes: {
|
||||
from: cursor,
|
||||
insert: insertText,
|
||||
},
|
||||
// the next 2 lines will set the appropriate cursor position after inserting the new text.
|
||||
selection: {anchor: cursor + 1},
|
||||
scrollIntoView: true,
|
||||
});
|
||||
|
||||
if (transaction) {
|
||||
codeMirrorView.dispatch(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
let language = new Compartment();
|
||||
let tabSize = new Compartment();
|
||||
@@ -51,7 +74,6 @@
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
tinymce.init({...config, ...additionalConfig});
|
||||
});
|
||||
|
||||
export function insertMedia(html){
|
||||
activeEditor.execCommand('InsertHTML', false, html);
|
||||
export function insertMedia(info){
|
||||
activeEditor.execCommand('InsertHTML', false, info.html);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
<script>
|
||||
import {onDestroy, onMount} from 'svelte';
|
||||
import {Editor} from '@tiptap/core'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Heading from '@tiptap/extension-heading'
|
||||
import Blockquote from '@tiptap/extension-blockquote';
|
||||
import Bold from '@tiptap/extension-bold';
|
||||
import BulletList from '@tiptap/extension-bullet-list';
|
||||
import Code from '@tiptap/extension-code';
|
||||
import History from '@tiptap/extension-history';
|
||||
import Italic from '@tiptap/extension-italic';
|
||||
import ListItem from '@tiptap/extension-list-item';
|
||||
import OrderedList from '@tiptap/extension-ordered-list';
|
||||
import Strike from '@tiptap/extension-strike';
|
||||
import Table from '@tiptap/extension-table';
|
||||
import TableRow from '@tiptap/extension-table-row';
|
||||
import TableCell from '@tiptap/extension-table-cell';
|
||||
import TableHeader from '@tiptap/extension-table-header';
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
|
||||
let element;
|
||||
let editor;
|
||||
export let value = "";
|
||||
|
||||
onMount(() => {
|
||||
editor = new Editor({
|
||||
element: element,
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
Bold,
|
||||
BulletList,
|
||||
Code,
|
||||
History,
|
||||
Italic,
|
||||
ListItem,
|
||||
OrderedList,
|
||||
ListItem,
|
||||
Strike,
|
||||
Table,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
Underline,
|
||||
Heading.configure({
|
||||
levels: [1, 2, 3],
|
||||
}),
|
||||
Blockquote
|
||||
],
|
||||
content: value,
|
||||
editable: true,
|
||||
onTransaction: () => {
|
||||
// force re-render so `editor.isActive` works as expected
|
||||
editor = editor;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (editor) {
|
||||
editor.destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if editor}
|
||||
<button
|
||||
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||
class:active={editor.isActive('heading', { level: 1 })}
|
||||
>
|
||||
H1
|
||||
</button>
|
||||
<button
|
||||
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||
class:active={editor.isActive('heading', { level: 2 })}
|
||||
>
|
||||
H2
|
||||
</button>
|
||||
<button
|
||||
on:click={() => editor.chain().focus().setParagraph().run()}
|
||||
class:active={editor.isActive('paragraph')}
|
||||
>
|
||||
P
|
||||
</button>
|
||||
<button
|
||||
on:click={() => editor.chain().focus().toggleBold().run()}
|
||||
class:active={editor.isActive('bold')}
|
||||
>
|
||||
Bold
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<div bind:this={element} class="content"/>
|
||||
@@ -1,21 +1,67 @@
|
||||
<script>
|
||||
import {onMount} from "svelte";
|
||||
import {onDestroy, onMount} from "svelte";
|
||||
import Trix from "trix"
|
||||
import customcss from "./tinymce.css?inline";
|
||||
import "trix/dist/trix.css"
|
||||
|
||||
export let value = "";
|
||||
let textareaEl;
|
||||
let lastVal;
|
||||
let editorWrapper;
|
||||
let activeEditor;
|
||||
export let field;
|
||||
let editor;
|
||||
|
||||
|
||||
function updateValue(e) {
|
||||
value = e.target.value;
|
||||
}
|
||||
|
||||
export function insertMedia(info){
|
||||
if(info.record._file.width > 0){
|
||||
var attachment = new Trix.Attachment({ content: info.html })
|
||||
editor.editor.insertAttachment(attachment)
|
||||
}else{
|
||||
editor.editor.insertHTML(`<a href="${info.originalUrl}">${info.record._file.originalName}</a>`)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
editor.addEventListener("trix-file-accept", (e) => {
|
||||
e.preventDefault();
|
||||
})
|
||||
|
||||
editor.addEventListener("trix-before-initialize", (e) => {
|
||||
Trix.config.blockAttributes.heading1.tagName = 'h2';
|
||||
const { toolbarElement } = e.target
|
||||
const h1Button = toolbarElement.querySelector("[data-trix-attribute=heading1]")
|
||||
h1Button.insertAdjacentHTML("afterend", `<button style="text-indent: initial;padding: 14px 10px !important;" type="button" class="trix-button trix-button--icon" data-trix-attribute="heading3" title="Heading 3" tabindex="-1" data-trix-active="">H3</button>`)
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
// onDestroy(() => {
|
||||
// editor.removeEventListener("trix-before-initialize")
|
||||
// })
|
||||
|
||||
|
||||
Trix.config.blockAttributes.default.breakOnReturn = false
|
||||
console.log(Trix.config)
|
||||
Trix.config.blockAttributes.heading3 = {
|
||||
tagName: 'h3',
|
||||
terminal: true,
|
||||
breakOnReturn: true,
|
||||
group: false
|
||||
}
|
||||
// console.log(Trix.config)
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={editorWrapper} class="tox-wrapper">
|
||||
<input bind:this={textareaEl} id="x" bind:value type="hidden">
|
||||
<trix-editor class="trix-content content" input="x"></trix-editor>
|
||||
<div class="tox-wrapper">
|
||||
<input id="x-{field.name}" {value} type="hidden">
|
||||
<trix-editor
|
||||
bind:this={editor}
|
||||
class=" content"
|
||||
input="x-{field.name}"
|
||||
role="textbox"
|
||||
tabindex="0"
|
||||
on:trix-change={updateValue}
|
||||
|
||||
></trix-editor>
|
||||
</div>
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
e.preventDefault();
|
||||
|
||||
let newRoles = [...member.roles, aRole];
|
||||
console.log(member.roles)
|
||||
console.log(aRole)
|
||||
console.log(newRoles)
|
||||
dispatch("update", {
|
||||
user: member.id,
|
||||
roles: newRoles,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import {afterUpdate, getContext, onMount} from "svelte";
|
||||
import {isEqual} from "lodash";
|
||||
import axios from "axios";
|
||||
import EditHeader from "./header/EditHeader.svelte"
|
||||
import FilePreview from "./FilePreview.svelte"
|
||||
@@ -10,6 +9,7 @@
|
||||
import Info from "./Info.svelte"
|
||||
import ErrorAlert from "../common/ErrorAlert.svelte"
|
||||
import Title from "./header/Title.svelte";
|
||||
import {hasDataChanged} from "./editor.js";
|
||||
|
||||
const channel = getContext("channel");
|
||||
|
||||
@@ -74,10 +74,7 @@
|
||||
}
|
||||
|
||||
function checkUnsavedData() {
|
||||
if (isCreateMode) {
|
||||
return false;
|
||||
}
|
||||
return !isEqual(originalContent, {
|
||||
return hasDataChanged(isCreateMode,originalContent,{
|
||||
data: record.data,
|
||||
schema: record.schema,
|
||||
status: record.status,
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
import Color from "./elements/Color.svelte";
|
||||
import Checkbox from "./elements/Checkbox.svelte";
|
||||
import Number from "./elements/Number.svelte";
|
||||
import Url from "./elements/Url.svelte";
|
||||
import Date from "./elements/Date.svelte";
|
||||
import UUID from "./elements/UUID.svelte";
|
||||
import File from "./elements/File.svelte";
|
||||
import Textarea from "./elements/Textarea.svelte";
|
||||
import Datetime from "./elements/Datetime.svelte";
|
||||
@@ -25,10 +23,8 @@
|
||||
color: Color,
|
||||
checkbox: Checkbox,
|
||||
number: Number,
|
||||
url: Url,
|
||||
date: Date,
|
||||
datetime: Datetime,
|
||||
uuid: UUID,
|
||||
json: Json,
|
||||
markdown: Markdown,
|
||||
};
|
||||
@@ -98,6 +94,16 @@
|
||||
bind:graph
|
||||
{record}
|
||||
/>
|
||||
{:else if field.info.name === "markdown"}
|
||||
<Markdown
|
||||
bind:value={data[field.name]}
|
||||
{schema}
|
||||
{field}
|
||||
{validationErrors}
|
||||
{isCreateMode}
|
||||
bind:graph
|
||||
{record}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={formElement}
|
||||
|
||||
@@ -13,13 +13,18 @@
|
||||
}
|
||||
|
||||
let backlinks = graph.parentEdges.map(edge => {
|
||||
let schema = channel.schemas.find((s) => s.name === edge.sourceSchema);
|
||||
const parentRecord = graph.records.find( record => record.id === edge.source);
|
||||
|
||||
let schema = channel.schemas.find((s) => s.name === parentRecord.schema);
|
||||
let edgeField = findEdgeField(schema,edge.field);
|
||||
if(!edgeField){
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
field: edgeField.label,
|
||||
record: graph.records.find( record => record.id === edge.source)
|
||||
record: parentRecord
|
||||
}
|
||||
})
|
||||
}).filter( edgeOrNull => !!edgeOrNull)
|
||||
</script>
|
||||
<div class="editor-field">
|
||||
{#each backlinks as backlink}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
import {friendlyDate} from "../../helpers";
|
||||
import Avatar from "../account/Avatar.svelte";
|
||||
import {usernameById} from "../account/users";
|
||||
import {isEqual} from "lodash";
|
||||
import Icon from "../common/Icon.svelte";
|
||||
import RevisionCell from "./revisions/RevisionCell.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import RevisionEdgeRow from "./revisions/RevisionEdgeRow.svelte";
|
||||
import axios from "axios";
|
||||
import {hasDataChanged} from "./editor.js";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let record;
|
||||
@@ -60,7 +61,7 @@
|
||||
selectedRevision = revision;
|
||||
|
||||
fieldsWithDiff = schema.fields.filter((f) => {
|
||||
return !isEqual(selectedRevision.data[f.name], record.data[f.name]);
|
||||
return hasDataChanged(false,selectedRevision.data[f.name], record.data[f.name]);
|
||||
});
|
||||
getEdgesByField(fieldsWithDiff, revision)
|
||||
revisionSection.scrollIntoView();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import {afterUpdate, createEventDispatcher, getContext, onMount} from "svelte";
|
||||
|
||||
import {isEqual} from "lodash";
|
||||
import {hasDataChanged} from "./editor.js";
|
||||
import FormField from "./FormField.svelte";
|
||||
import FilePreview from "./FilePreview.svelte";
|
||||
import ContentTabs from "./header/ContentTabs.svelte";
|
||||
@@ -80,10 +79,7 @@
|
||||
}
|
||||
|
||||
function checkUnsavedData() {
|
||||
if (isCreateMode) {
|
||||
return false;
|
||||
}
|
||||
return !isEqual(originalContent, {
|
||||
return hasDataChanged(isCreateMode, originalContent, {
|
||||
data: record.data,
|
||||
schema: record.schema,
|
||||
status: record.status,
|
||||
|
||||
@@ -13,11 +13,8 @@
|
||||
{#if record?.data}
|
||||
<a
|
||||
href="{channel.lucentUrl}/records/{record.id}"
|
||||
class="text-decoration-none rounded py-1 px-2 d-inline-block"
|
||||
{title}
|
||||
style="border:2px solid {!schema.color
|
||||
? '#999'
|
||||
: schema.color}!important;white-space: nowrap;"
|
||||
class="reference"
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export function hasDataChanged(isCreateMode, originalContent, newContent){
|
||||
if (isCreateMode) {
|
||||
return false;
|
||||
}
|
||||
return JSON.stringify(originalContent) !== JSON.stringify(newContent);
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
<script>
|
||||
import {onMount} from "svelte";
|
||||
import flatpickr from "flatpickr";
|
||||
import "flatpickr/dist/flatpickr.css";
|
||||
import "flatpickr/dist/themes/light.css";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
|
||||
export let field;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
<script>
|
||||
import {onMount} from "svelte";
|
||||
import flatpickr from "flatpickr";
|
||||
import "flatpickr/dist/flatpickr.css";
|
||||
import "flatpickr/dist/themes/light.css";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
|
||||
export let field;
|
||||
export let value;
|
||||
export let isCreateMode;
|
||||
export let validationErrors;
|
||||
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
||||
|
||||
export let id;
|
||||
let wrapperDiv;
|
||||
let pickerInput;
|
||||
let pickerInstance;
|
||||
let flatpickrOptions = {
|
||||
appendTo: wrapperDiv,
|
||||
static: true,
|
||||
allowInput: true,
|
||||
altInput: true,
|
||||
altFormat: "Y-m-d H:i:S",
|
||||
@@ -40,7 +42,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
<div class="mb-0" bind:this={wrapperDiv}>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -4,7 +4,13 @@
|
||||
import PreviewFile from "../previews/PreviewFile.svelte";
|
||||
import Dropdown from "../../common/Dropdown.svelte";
|
||||
import Dialog from "../../dialog/Dialog.svelte";
|
||||
import {insertEdges} from "./reference.js";
|
||||
import {
|
||||
fullDeleteRecord,
|
||||
graphToReferences,
|
||||
insertEdges,
|
||||
removeReferenceFromGraph,
|
||||
restoreReferenceToGraph
|
||||
} from "./reference.js";
|
||||
import {getContext} from "svelte";
|
||||
|
||||
const channel = getContext("channel");
|
||||
@@ -12,11 +18,7 @@
|
||||
export let record;
|
||||
export let graph
|
||||
let browseModal;
|
||||
$: references = graph?.edges
|
||||
.filter((edge) => edge.field === field.name)
|
||||
.map((edge) => {
|
||||
return graph.records.find((increc) => increc.id === edge.target && record.id === edge.source);
|
||||
}).filter((rec) => (rec?.id ? true : false)) ?? [];
|
||||
$: references = graphToReferences(graph, record, field)
|
||||
|
||||
let collections = channel.schemas.filter((aschema) =>
|
||||
field.collections.includes(aschema.name)
|
||||
@@ -24,9 +26,17 @@
|
||||
|
||||
function removeReference(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = graph.edges.filter(
|
||||
(edge) => !(edge.target === e.detail && edge.field === field.name)
|
||||
);
|
||||
graph.edges = removeReferenceFromGraph(graph, field, e.detail)
|
||||
}
|
||||
|
||||
function restoreReference(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = restoreReferenceToGraph(graph, field, e.detail)
|
||||
}
|
||||
|
||||
function fullDelete(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = fullDeleteRecord(channel,graph, field, e.detail)
|
||||
}
|
||||
|
||||
function openBrowseModal(e, schema) {
|
||||
@@ -73,10 +83,17 @@
|
||||
</div>
|
||||
{#if references.length > 0}
|
||||
<Sortable sortableClass="mt-3" on:update={reorder}>
|
||||
{#each references as reference (reference.id)}
|
||||
{#each references as reference (reference.record.id)}
|
||||
<!--This div helps the sorting thing-->
|
||||
<div>
|
||||
<PreviewFile record={reference} hasDelete={true} on:remove={removeReference}></PreviewFile>
|
||||
<PreviewFile
|
||||
record={reference.record}
|
||||
edge={reference.edge}
|
||||
hasDelete={true}
|
||||
on:remove={removeReference}
|
||||
on:restore={restoreReference}
|
||||
on:fulldelete={fullDelete}
|
||||
></PreviewFile>
|
||||
</div>
|
||||
{/each}
|
||||
</Sortable>
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
<script>
|
||||
import Codemirror from "../../libs/CodemirrorMarkdown.svelte";
|
||||
import { getErrorMessage } from "./errorMessage";
|
||||
import RichEditorFiles from "./RichEditorFiles.svelte";
|
||||
|
||||
|
||||
export let value;
|
||||
export let field;
|
||||
export let graph;
|
||||
export let record;
|
||||
export let isCreateMode;
|
||||
// export let id;
|
||||
export let validationErrors;
|
||||
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
||||
let editor;
|
||||
|
||||
function insertMedia(e){
|
||||
editor.insertMedia(e.detail)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-3">
|
||||
|
||||
<Codemirror bind:value editable={!field.readonly || isCreateMode} />
|
||||
|
||||
<Codemirror bind:this={editor} bind:value editable={!field.readonly || isCreateMode} />
|
||||
{#if field.collections.length > 0}
|
||||
<RichEditorFiles
|
||||
bind:graph
|
||||
{record}
|
||||
{field}
|
||||
{validationErrors}
|
||||
on:editor-insert={insertMedia}
|
||||
>
|
||||
</RichEditorFiles>
|
||||
{/if}
|
||||
{#if errorMessage}
|
||||
<div class="invalid-feedback d-block">
|
||||
{errorMessage}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import {insertEdges} from "./reference";
|
||||
import {
|
||||
fullDeleteRecord,
|
||||
graphToReferences,
|
||||
insertEdges,
|
||||
removeReferenceFromGraph,
|
||||
restoreReferenceToGraph
|
||||
} from "./reference";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
import {sortByField} from "../../edges/sortEdges";
|
||||
import ReferenceInlineButtons from "./ReferenceInlineButtons.svelte";
|
||||
import Sortable from "../../libs/Sortable.svelte";
|
||||
import PreviewReference from "../previews/PreviewReference.svelte";
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let record;
|
||||
@@ -16,11 +21,7 @@
|
||||
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
||||
|
||||
|
||||
$: references = graph.edges
|
||||
.filter((edge) => edge.field === field.name)
|
||||
.map((edge) => {
|
||||
return graph.records.find((increc) => increc.id === edge.target && record.id === edge.source);
|
||||
}).filter((rec) => (rec?.id ? true : false)) ?? [];
|
||||
$: references = graphToReferences(graph,record,field)
|
||||
|
||||
let collections = channel.schemas.filter((aschema) =>
|
||||
field.collections.includes(aschema.name)
|
||||
@@ -28,27 +29,25 @@
|
||||
|
||||
function removeReference(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = graph.edges.filter(
|
||||
(edge) => !(edge.target === e.detail && edge.field === field.name)
|
||||
);
|
||||
graph.edges = removeReferenceFromGraph(graph,field,e.detail)
|
||||
}
|
||||
|
||||
function restoreReference(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = restoreReferenceToGraph(graph,field,e.detail)
|
||||
}
|
||||
|
||||
function fullDelete(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = fullDeleteRecord(channel,graph, field, e.detail)
|
||||
}
|
||||
|
||||
function reorder(e) {
|
||||
|
||||
graph.edges = sortByField(e.detail.source, e.detail.target, graph.edges, field.name, references);
|
||||
}
|
||||
|
||||
function insert(e) {
|
||||
e.preventDefault();
|
||||
// axios.post(channel.lucentUrl + "/edges/insert-many", {
|
||||
// source: record.id,
|
||||
// sourceSchema: record.schema,
|
||||
// targetSchema: e.detail.schema,
|
||||
// field: field.name,
|
||||
// targets: e.detail.records.map(r => r.id),
|
||||
// }).then(function (response) {
|
||||
// graph = response.data.graph;
|
||||
// })
|
||||
graph = insertEdges(graph, record, e.detail.records, field.name, e.detail.action);
|
||||
}
|
||||
|
||||
@@ -69,13 +68,16 @@
|
||||
</div>
|
||||
{#if references.length > 0}
|
||||
<Sortable sortableClass="row row-cols-3 mt-3" on:update={reorder}>
|
||||
{#each references as reference (reference.id)}
|
||||
{#each references as reference (reference.record.id)}
|
||||
<div>
|
||||
<PreviewReference
|
||||
{graph}
|
||||
record={reference}
|
||||
record={reference.record}
|
||||
edge={reference.edge}
|
||||
hasDelete={true}
|
||||
on:remove={removeReference}
|
||||
on:restore={restoreReference}
|
||||
on:fulldelete={fullDelete}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
function createInlineReference(e, schemaUId) {
|
||||
e.preventDefault();
|
||||
inLineCreateRecord = null;
|
||||
axios
|
||||
.get(channel.lucentUrl + "/records/newInline?schema=" + schemaUId)
|
||||
.then((response) => {
|
||||
@@ -59,27 +60,29 @@
|
||||
<div
|
||||
style="display: flex;align-items: center;gap:4px"
|
||||
>
|
||||
{#each schemas as schema}
|
||||
<Dropdown>
|
||||
<div slot="button" class:is-first={!recordId}>
|
||||
{schema.label}
|
||||
</div>
|
||||
<Dropdown>
|
||||
<div slot="button">New</div>
|
||||
{#each schemas as schema}
|
||||
<button
|
||||
class=" button"
|
||||
on:click={(e) =>
|
||||
createInlineReference(e, schema.name)}
|
||||
>Create New Record
|
||||
>{schema.label}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
</Dropdown>
|
||||
<Dropdown>
|
||||
<div slot="button"> <Icon icon="magnifying-glass"/></div>
|
||||
{#each schemas as schema}
|
||||
<button
|
||||
class="button"
|
||||
on:click={(e) => openBrowseModal(e, schema.name)}
|
||||
>
|
||||
<Icon icon="magnifying-glass"/>
|
||||
Search
|
||||
</button
|
||||
>
|
||||
</Dropdown>
|
||||
{/each}
|
||||
>{schema.label}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
</Dropdown>
|
||||
</div>
|
||||
{:else}
|
||||
<div style="display:flex;align-items: center;gap: 4px">
|
||||
@@ -100,9 +103,9 @@
|
||||
|
||||
<DialogRecord bind:this={dialogRecord}>
|
||||
{#if inLineCreateRecord}
|
||||
|
||||
<InlineEdit
|
||||
{...inLineCreateRecord}
|
||||
isCreateMode={true}
|
||||
on:cancel={(e) => (inLineCreateRecord = null)}
|
||||
on:inlinesaved={save}
|
||||
/>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import {debounce} from "lodash";
|
||||
import {debounce} from "../../../debounce.js";
|
||||
import {previewTitle} from "../Preview";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
import {insertEdges} from "./reference.js";
|
||||
import Icon from "../../common/Icon.svelte";
|
||||
import axios from "axios";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let field;
|
||||
@@ -18,7 +19,7 @@
|
||||
$: references = graph.edges
|
||||
.filter((edge) => edge.field === field.name)
|
||||
.map((edge) => {
|
||||
return graph.records.find((increc) => increc.id == edge.target && record.id == edge.source);
|
||||
return graph.records.find((increc) => increc.id === edge.target && record.id === edge.source);
|
||||
}).filter((rec) => (rec?.id ? true : false)) ?? [];
|
||||
|
||||
let search = ""
|
||||
@@ -48,11 +49,9 @@
|
||||
.then((response) => {
|
||||
searchOptions = [];
|
||||
insert(e, response.data.records[0]);
|
||||
console.log(response)
|
||||
})
|
||||
.catch((error) => {
|
||||
searchOptions = [];
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +78,6 @@
|
||||
})
|
||||
.catch((error) => {
|
||||
searchOptions = [];
|
||||
console.log(error);
|
||||
});
|
||||
}, 500);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import Tinymce from "../../libs/Tinymce.svelte";
|
||||
import RichEditorFiles from "./RichEditorFiles.svelte";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
import Trix from "../../libs/Trix.svelte";
|
||||
|
||||
export let value;
|
||||
export let field;
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
<div class="mb-0">
|
||||
|
||||
|
||||
<Tinymce bind:this={editor} bind:value {additionalConfig}/>
|
||||
<Trix {field} bind:this={editor} bind:value></Trix>
|
||||
{#if field.collections.length > 0}
|
||||
<RichEditorFiles
|
||||
bind:graph
|
||||
@@ -38,7 +37,7 @@
|
||||
|
||||
</RichEditorFiles>
|
||||
{/if}
|
||||
<!-- <TipTap bind:value />-->
|
||||
|
||||
|
||||
{#if errorMessage}
|
||||
<div class="invalid-feedback d-block">
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script>
|
||||
import {sortByField} from "../../edges/sortEdges";
|
||||
import Sortable from "../../libs/Sortable.svelte";
|
||||
import PreviewFile from "../previews/PreviewFile.svelte";
|
||||
import Dropdown from "../../common/Dropdown.svelte";
|
||||
import Dialog from "../../dialog/Dialog.svelte";
|
||||
@@ -70,7 +68,8 @@
|
||||
{#each references as reference (reference.id)}
|
||||
<!--This div helps the sorting thing-->
|
||||
<div>
|
||||
<PreviewFile record={reference} hasDelete={true} hasInsert={true} on:remove={removeReference} on:editor-insert></PreviewFile>
|
||||
<PreviewFile record={reference} hasDelete={true} hasInsert={true} on:remove={removeReference}
|
||||
on:editor-insert></PreviewFile>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<script>
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getContext } from "svelte";
|
||||
import Icon from "../../common/Icon.svelte";
|
||||
import { getErrorMessage } from "./errorMessage";
|
||||
const channelurl = getContext("channelurl");
|
||||
export let validationErrors;
|
||||
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
||||
export let field;
|
||||
export let value;
|
||||
export let id;
|
||||
export let isCreateMode;
|
||||
let readonly = field.readonly && !isCreateMode;
|
||||
|
||||
function generateId(e) {
|
||||
e.preventDefault();
|
||||
value = uuidv4();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<input
|
||||
type="text"
|
||||
{id}
|
||||
class="form-control"
|
||||
class:is-invalid={errorMessage}
|
||||
bind:value
|
||||
autocomplete="off"
|
||||
{readonly}
|
||||
/>
|
||||
{#if !readonly}
|
||||
<button
|
||||
class="btn btn-primary ms-2"
|
||||
title="Generate a new UUIDv4"
|
||||
on:click={generateId}
|
||||
>
|
||||
<Icon icon="dice" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if errorMessage}
|
||||
<div class="invalid-feedback d-block">
|
||||
{errorMessage}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,30 +0,0 @@
|
||||
<script>
|
||||
import { uniqueId } from "lodash";
|
||||
import { getContext } from "svelte";
|
||||
const channelurl = getContext("channelurl");
|
||||
export let field;
|
||||
export let value;
|
||||
export let schema;
|
||||
let id = uniqueId();
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
<div class="d-flex justify-content-between">
|
||||
<label for={id} class="form-label">{field.label}</label>
|
||||
<a
|
||||
class="text-decoration-none"
|
||||
href="{channelurl}/schemas/{schema.name}/fields/edit/{field.name}"
|
||||
><code class="text-primary opacity-50">{field.name}</code></a
|
||||
>
|
||||
</div>
|
||||
<input
|
||||
type="url"
|
||||
{id}
|
||||
class="form-control"
|
||||
bind:value
|
||||
placeholder="https://www.example.com"
|
||||
/>
|
||||
{#if field.help}
|
||||
<small class=" text-primary opacity-50">{field.help}</small>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,12 +1,11 @@
|
||||
import {uniqBy} from "lodash";
|
||||
import {uniqueBy} from "../../../helpers.js";
|
||||
import axios from "axios";
|
||||
|
||||
export function insertEdges(graph, sourceRecord, targetRecords, fieldName, action = "") {
|
||||
let newEdges = targetRecords.map((r) => {
|
||||
return {
|
||||
target: r.id,
|
||||
source: sourceRecord.id,
|
||||
sourceSchema: sourceRecord.schema,
|
||||
targetSchema: r.schema,
|
||||
field: fieldName,
|
||||
depth: 1,
|
||||
rank: ""
|
||||
@@ -18,7 +17,53 @@ export function insertEdges(graph, sourceRecord, targetRecords, fieldName, actio
|
||||
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
|
||||
}
|
||||
|
||||
graph.records = uniqBy([...graph.records, ...targetRecords], (r) => r.id);
|
||||
graph.edges = uniqBy([...replacedEdges, ...newEdges], (edge) => edge.source + edge.target + edge.field + edge.depth);
|
||||
graph.records = uniqueBy([...graph.records, ...targetRecords], (r) => r.id);
|
||||
graph.edges = uniqueBy([...replacedEdges, ...newEdges], (edge) => edge.source + edge.target + edge.field + edge.depth);
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
export function graphToReferences(graph,record,field){
|
||||
return graph.edges
|
||||
.filter((edge) => edge.field === field.name)
|
||||
.map((edge) => {
|
||||
return {
|
||||
record: graph.records.find((increc) => increc.id === edge.target && record.id === edge.source),
|
||||
edge: edge
|
||||
};
|
||||
}).filter((rec) => (rec.record?.id ? true : false)) ?? [];
|
||||
}
|
||||
|
||||
export function removeReferenceFromGraph(graph,field,id){
|
||||
return graph.edges.map(
|
||||
(edge) => {
|
||||
if(edge.target === id && edge.field === field.name){
|
||||
edge._isTrashed = true;
|
||||
}
|
||||
return edge;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function restoreReferenceToGraph(graph,field,id){
|
||||
return graph.edges.map(
|
||||
(edge) => {
|
||||
if(edge.target === id && edge.field === field.name){
|
||||
edge._isTrashed = false;
|
||||
}
|
||||
return edge;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export function fullDeleteRecord(channel,graph,field,id){
|
||||
axios
|
||||
.post(channel.lucentUrl + "/records/status/trashed" , {
|
||||
records: [id]
|
||||
});
|
||||
|
||||
return graph.edges.filter(
|
||||
(edge) => !(edge.target === id && edge.field === field.name)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
import {createEventDispatcher, getContext} from "svelte";
|
||||
import Preview from "../../files/Preview.svelte";
|
||||
import {previewTitle} from "./../Preview";
|
||||
import {htmlurl} from "../../files/imageserver.js"
|
||||
import {fileurl, htmlurl} from "../../files/imageserver.js"
|
||||
import Status from "./../Status.svelte";
|
||||
import Dropdown from "../../common/Dropdown.svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const channel = getContext("channel");
|
||||
export let record;
|
||||
export let edge;
|
||||
export let hasDelete = false;
|
||||
export let hasInsert = false;
|
||||
|
||||
@@ -23,15 +24,31 @@
|
||||
dispatch("remove", record.id);
|
||||
}
|
||||
|
||||
function restore(e) {
|
||||
e.preventDefault();
|
||||
dispatch("restore", record.id);
|
||||
}
|
||||
|
||||
function fullDelete(e) {
|
||||
e.preventDefault();
|
||||
dispatch("fulldelete", record.id);
|
||||
}
|
||||
|
||||
function insert(e, preset) {
|
||||
e.preventDefault();
|
||||
let html = htmlurl(channel,record, preset)
|
||||
dispatch("editor-insert", html);
|
||||
let html = htmlurl(channel, record, preset)
|
||||
let url = !preset ? `/${record._file.path}` : `/templates/${preset}/${record._file.path}`;
|
||||
dispatch("editor-insert", {
|
||||
html: html,
|
||||
url: channel.filesUrl + url,
|
||||
originalUrl: channel.filesUrl + "/" + record._file.path,
|
||||
record: record
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="preview-file">
|
||||
<div class="preview-file" class:is-trashed={edge?._isTrashed}>
|
||||
<div style="display: flex;align-items: center;gap: 10px;">
|
||||
<div class="image">
|
||||
<Preview {record} size="small"/>
|
||||
@@ -43,6 +60,9 @@
|
||||
href="{channel.lucentUrl}/records/{record.id}"
|
||||
>
|
||||
{cardTitle}
|
||||
{#if edge?._isTrashed}
|
||||
<span class="trashed-text">will remove on save</span>
|
||||
{/if}
|
||||
</a>
|
||||
<small class="d-block">
|
||||
from {schema.label}
|
||||
@@ -72,12 +92,30 @@
|
||||
{/if}
|
||||
{#if hasDelete}
|
||||
<div class="reference-action">
|
||||
<button
|
||||
class="button"
|
||||
on:click={remove}
|
||||
>
|
||||
<Icon icon="trash-can"/>
|
||||
</button>
|
||||
{#if edge?._isTrashed}
|
||||
<button
|
||||
title="Restore"
|
||||
class="button"
|
||||
on:click={restore}
|
||||
>
|
||||
<Icon icon="undo"/>
|
||||
</button>
|
||||
<button
|
||||
title="Delete from everywhere"
|
||||
class="button"
|
||||
on:click={fullDelete}
|
||||
>
|
||||
<Icon icon="destroy"/>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
title="Remove"
|
||||
class="button"
|
||||
on:click={remove}
|
||||
>
|
||||
<Icon icon="trash-can"/>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -10,21 +10,32 @@
|
||||
const channel = getContext("channel");
|
||||
export let graph;
|
||||
export let record;
|
||||
export let edge;
|
||||
export let hasDelete = false;
|
||||
|
||||
let schema = channel.schemas.find((aschema) => aschema.name === record.schema);
|
||||
let cardTitle = previewTitle(channel.schemas, record, graph);
|
||||
const cardImageEdge = graph.edges.find(e => e.source === record.id && e.field === schema.cardImage);
|
||||
const cardImageEdge = graph.edges.find(e => e.source === record.id && e.field === schema.cardImage);
|
||||
let cardImageRecord = graph.records.find(r => r.id === cardImageEdge?.target);
|
||||
|
||||
function remove(e) {
|
||||
e.preventDefault();
|
||||
dispatch("remove", record.id);
|
||||
}
|
||||
|
||||
function restore(e) {
|
||||
e.preventDefault();
|
||||
dispatch("restore", record.id);
|
||||
}
|
||||
|
||||
function fullDelete(e) {
|
||||
e.preventDefault();
|
||||
dispatch("fulldelete", record.id);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<div class="preview-reference">
|
||||
<div class="preview-reference" class:is-trashed={edge?._isTrashed}>
|
||||
<div style="display: flex;align-items: center;gap: 10px;">
|
||||
|
||||
{#if cardImageRecord}
|
||||
@@ -38,7 +49,12 @@
|
||||
class="record-title"
|
||||
href="{channel.lucentUrl}/records/{record.id}"
|
||||
>
|
||||
|
||||
{cardTitle}
|
||||
{#if edge?._isTrashed}
|
||||
<span class="trashed-text">will remove on save</span>
|
||||
{/if}
|
||||
|
||||
</a>
|
||||
<small class="d-block">
|
||||
from {schema.label}
|
||||
@@ -53,12 +69,30 @@
|
||||
</div>
|
||||
{#if hasDelete}
|
||||
<div class="reference-action">
|
||||
<button
|
||||
class="button"
|
||||
on:click={remove}
|
||||
>
|
||||
<Icon icon="trash-can"/>
|
||||
</button>
|
||||
{#if edge?._isTrashed}
|
||||
<button
|
||||
title="Restore"
|
||||
class="button"
|
||||
on:click={restore}
|
||||
>
|
||||
<Icon icon="undo"/>
|
||||
</button>
|
||||
<button
|
||||
title="Delete from everywhere"
|
||||
class="button"
|
||||
on:click={fullDelete}
|
||||
>
|
||||
<Icon icon="destroy"/>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
title="Remove"
|
||||
class="button"
|
||||
on:click={remove}
|
||||
>
|
||||
<Icon icon="trash-can"/>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Generated
+3414
-1044
File diff suppressed because it is too large
Load Diff
+4
-25
@@ -11,41 +11,20 @@
|
||||
"@codemirror/lang-markdown": "^6.2.5",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||
"@tiptap/core": "^2.6.4",
|
||||
"@tiptap/extension-blockquote": "^2.6.4",
|
||||
"@tiptap/extension-bold": "^2.6.4",
|
||||
"@tiptap/extension-bullet-list": "^2.6.4",
|
||||
"@tiptap/extension-code": "^2.6.4",
|
||||
"@tiptap/extension-document": "^2.6.4",
|
||||
"@tiptap/extension-heading": "^2.6.4",
|
||||
"@tiptap/extension-history": "^2.6.4",
|
||||
"@tiptap/extension-italic": "^2.6.4",
|
||||
"@tiptap/extension-list-item": "^2.6.4",
|
||||
"@tiptap/extension-ordered-list": "^2.6.4",
|
||||
"@tiptap/extension-paragraph": "^2.6.4",
|
||||
"@tiptap/extension-strike": "^2.6.4",
|
||||
"@tiptap/extension-table": "^2.6.4",
|
||||
"@tiptap/extension-table-cell": "^2.6.4",
|
||||
"@tiptap/extension-table-header": "^2.6.4",
|
||||
"@tiptap/extension-table-row": "^2.6.4",
|
||||
"@tiptap/extension-text": "^2.6.4",
|
||||
"@tiptap/extension-underline": "^2.6.4",
|
||||
"@tiptap/pm": "^2.6.4",
|
||||
"axios": "^1.7.4",
|
||||
"codemirror": "^6.0.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"flatpickr": "^4.6.13",
|
||||
"fuse.js": "^7.0.0",
|
||||
"htmx.org": "^2.0.1",
|
||||
"install": "^0.13.0",
|
||||
"laravel-vite-plugin": "^1.0.5",
|
||||
"lodash": "^4.17.21",
|
||||
"mustache": "^4.2.0",
|
||||
"postcss": "8.4.31",
|
||||
"sass": "^1.77.8",
|
||||
"npm": "^10.8.2",
|
||||
"sortablejs": "^1.15.2",
|
||||
"svelte": "^4.2.18",
|
||||
"tinymce": "^6.8.4",
|
||||
"uuid": "^10.0.0",
|
||||
"vite": "5.2.6"
|
||||
"trix": "^2.1.5",
|
||||
"vite": "5.4.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.scope-login {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
|
||||
.bg-image {
|
||||
width: 50%;
|
||||
background: url("/vendor/lucent/public/art.jpg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.login-form{
|
||||
width: 50%;
|
||||
height: 100vh;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.autocomplete {
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
overflow: visible;
|
||||
.autocomplete-option {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 3px 10px;
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
&:focus-within {
|
||||
.autocomplete-results{
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.autocomplete-selected-value {
|
||||
font-size: 13px;
|
||||
margin-top: 10px;
|
||||
border-radius: 12px;
|
||||
background: var(--p30);
|
||||
padding: 3px 10px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
line-height: 22px;
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete-results {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
border-radius: 12px;
|
||||
z-index: 20;
|
||||
background: var(--p30);
|
||||
//border: 1px solid var(--p40);
|
||||
transition: 600ms;
|
||||
flex-grow: 1;
|
||||
top: 45px;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.avatar {
|
||||
/* Center the content */
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
/* Used to position the content */
|
||||
position: relative;
|
||||
|
||||
/* Colors */
|
||||
|
||||
color: #fff;
|
||||
|
||||
/* Rounded border */
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar__letters {
|
||||
/* Center the content */
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
.button {
|
||||
border-radius: 12px;
|
||||
background: var(--p20);
|
||||
padding: 3px 10px;
|
||||
cursor: pointer;
|
||||
border: 0px solid var(--p30);
|
||||
font-size: 14px;
|
||||
min-height: 27px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--text);
|
||||
|
||||
&:focus {
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--p50) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background: var(--p30);
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background: var(--p70);
|
||||
color: var(--p10);
|
||||
|
||||
&:hover {
|
||||
background: var(--p90);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&[disabled] {
|
||||
pointer-events: none;
|
||||
opacity: .7;
|
||||
color: var(--text);
|
||||
}
|
||||
}
|
||||
|
||||
.upload-button {
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
font-weight: normal;
|
||||
background: var(--p80) !important;
|
||||
color: var(--p10);
|
||||
}
|
||||
}
|
||||
|
||||
.button-text {
|
||||
border: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.spinner-border {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 2px solid var(--p10);
|
||||
border-bottom-color: var(--p30);
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
animation: rotation 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
|
||||
@supports (-webkit-appearance: none) or (-moz-appearance: none) {
|
||||
.checkbox-wrapper input[type=checkbox] {
|
||||
--active-inner: var(--p10);
|
||||
--focus: 2px var(--p30);
|
||||
--border-hover: var(--p30);
|
||||
--disabled: #F6F8FF;
|
||||
--disabled-inner: #E1E6F9;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
height: 21px;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--bc, var(--p30));
|
||||
background: var(--b, var(--p10));
|
||||
transition: background 0.3s, border-color 0.3s, box-shadow 0.2s;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:after {
|
||||
content: "";
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
transition: transform var(--d-t, 0.3s) var(--d-t-e, ease), opacity var(--d-o, 0.2s);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:checked {
|
||||
--b: var(--p40);
|
||||
--bc: var(--p40);
|
||||
--d-o: .3s;
|
||||
--d-t: .6s;
|
||||
--d-t-e: cubic-bezier(.2, .85, .32, 1.2);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:disabled {
|
||||
--b: var(--disabled);
|
||||
cursor: not-allowed;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:disabled:checked {
|
||||
--b: var(--disabled-inner);
|
||||
--bc: var(--p40);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:disabled + label {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:hover:not(:checked):not(:disabled) {
|
||||
--bc: var(--border-hover);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:focus {
|
||||
box-shadow: 0 0 0 var(--focus);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch) {
|
||||
width: 21px;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch):after {
|
||||
opacity: var(--o, 0);
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch):checked {
|
||||
--o: 1;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox] + label {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch) {
|
||||
border-radius: 7px;
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch):after {
|
||||
width: 5px;
|
||||
height: 9px;
|
||||
border: 2px solid var(--active-inner);
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
left: 7px;
|
||||
top: 4px;
|
||||
transform: rotate(var(--r, 20deg));
|
||||
}
|
||||
.checkbox-wrapper input[type=checkbox]:not(.switch):checked {
|
||||
--r: 43deg;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-wrapper * {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
.checkbox-wrapper *:before,
|
||||
.checkbox-wrapper *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
.checkbox-wrapper input[type=checkbox]:indeterminate {
|
||||
--b: var(--p40);
|
||||
--bc: var(--p40);
|
||||
--d-o: .3s;
|
||||
--d-t: .6s;
|
||||
--d-t-e: cubic-bezier(.2, .85, .32, 1.2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.is-editable-false{
|
||||
.cm-content{
|
||||
background-color: var(--p10);
|
||||
}
|
||||
}
|
||||
.cm-focused{
|
||||
|
||||
.cm-content{
|
||||
background-color: var(--p10);
|
||||
color: var(--p100);
|
||||
}
|
||||
}
|
||||
|
||||
.cm-content{
|
||||
background-color: var(--p20);
|
||||
|
||||
}
|
||||
.ͼ4 .cm-line ::selection, .ͼ4 .cm-line::selection{
|
||||
background: var(--p40) !important;
|
||||
}
|
||||
|
||||
.cm-activeLine{
|
||||
background-color: var(--p20)!important;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
.flatpickr-wrapper {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.editor-field {
|
||||
.flatpickr-calendar {
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
.flatpickr-months .flatpickr-month {
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flatpickr-current-month .flatpickr-monthDropdown-months {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
.flatpickr-weekdays{
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
|
||||
}
|
||||
|
||||
.flatpickr-weekdaycontainer .flatpickr-weekday{
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.flatpickr-days{
|
||||
background: var(--p10);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.flatpickr-time{
|
||||
background: var(--p10);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
//:modal {
|
||||
// background-color: beige;
|
||||
// border: 2px solid burlywood;
|
||||
// border-radius: 5px;
|
||||
//}
|
||||
|
||||
html {
|
||||
//scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
body:has(dialog[open]) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
dialog {
|
||||
margin: 2vh auto;
|
||||
background-color: var(--p10);
|
||||
padding: 34px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
overflow: auto;
|
||||
max-height: 96vh;
|
||||
box-shadow: none!important;
|
||||
//position: relative;
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.dialog-body {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dialog::backdrop {
|
||||
|
||||
backdrop-filter: blur(3px);
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
position: sticky;
|
||||
top: -34px;
|
||||
z-index: 999;
|
||||
background-color: var(--p10);
|
||||
padding: 10px 0;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
.dropdown {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.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: 22;
|
||||
background: var(--p20);
|
||||
transition: 600ms;
|
||||
flex-grow: 1;
|
||||
top: 35px;
|
||||
min-width: max-content;
|
||||
border: 1px solid var(--p30);
|
||||
|
||||
|
||||
&.orientation-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.orientation-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.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(--p30);
|
||||
border-radius: 12px;
|
||||
|
||||
button {
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.editor-field{
|
||||
.dropdown-menu {
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-weight: 700;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
input[type=text],input[type=number],input[type=search],input[type=email],textarea{
|
||||
width: 100%;
|
||||
background: var(--p20);
|
||||
border: 1px solid var(--p50);
|
||||
border-radius: 5px;
|
||||
padding: 5px 7px;
|
||||
font-size: 16px;
|
||||
&:focus{
|
||||
background: var(--p10);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
textarea{
|
||||
resize: none;
|
||||
}
|
||||
|
||||
select{
|
||||
width: 100%;
|
||||
background: var(--p20);
|
||||
border: 1px solid var(--p50);
|
||||
border-radius: 5px;
|
||||
padding: 5px 7px;
|
||||
font-size: 16px;
|
||||
&:focus{
|
||||
background: var(--p10);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.htmx-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.htmx-request .htmx-indicator {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.htmx-request.htmx-indicator {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
.bt {
|
||||
appearance: none;
|
||||
background-color: #000;
|
||||
background-image: none;
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
box-shadow: #fff 4px 4px 0 0, #000 4px 4px 0 1px;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-family: ITCAvantGardeStd-Bk, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
margin: 0 5px 10px 0;
|
||||
overflow: visible;
|
||||
padding: 8px 40px;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
touch-action: manipulation;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bt:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bt:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bt:active {
|
||||
box-shadow: rgba(0, 0, 0, .125) 0 3px 5px inset;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.bt:not([disabled]):active {
|
||||
box-shadow: #fff 2px 2px 0 0, #000 2px 2px 0 1px;
|
||||
transform: translate(2px, 2px);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
.mt-1{margin-top: 4px}
|
||||
.mt-2{margin-top: 8px}
|
||||
.mt-3{margin-top: 12px}
|
||||
.mt-4{margin-top: 16px}
|
||||
.mt-5{margin-top: 20px}
|
||||
|
||||
.mb-1{margin-bottom: 4px}
|
||||
.mb-2{margin-bottom: 8px}
|
||||
.mb-3{margin-bottom: 12px}
|
||||
.mb-4{margin-bottom: 16px}
|
||||
.mb-5{margin-bottom: 20px}
|
||||
|
||||
.pt-1{padding-top: 4px}
|
||||
.pt-2{padding-top: 8px}
|
||||
.pt-3{padding-top: 12px}
|
||||
.pt-4{padding-top: 16px}
|
||||
.pt-5{padding-top: 20px}
|
||||
|
||||
.pb-1{padding-bottom: 4px}
|
||||
.pb-2{padding-bottom: 8px}
|
||||
.pb-3{padding-bottom: 12px}
|
||||
.pb-4{padding-bottom: 16px}
|
||||
.pb-5{padding-bottom: 20px}
|
||||
|
||||
.gap-1{gap: 4px}
|
||||
.gap-2{gap: 8px}
|
||||
.gap-3{gap: 12px}
|
||||
.gap-4{gap: 16px}
|
||||
.gap-5{gap: 20px}
|
||||
|
||||
.hide{
|
||||
display: none!important;
|
||||
}
|
||||
.hidden{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.d-block{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.d-inline-block{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.is-bold{
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.in-place{
|
||||
padding: 36px;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
.sidebar-content{
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
min-width: 900px;
|
||||
}
|
||||
|
||||
.main-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
.member-list{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
.member-item{
|
||||
background: var(--p30);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.member-name{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
.notice {
|
||||
background-color: var(--p20);
|
||||
padding: 14px;
|
||||
margin: 2rem 0;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
border-radius: 12px;
|
||||
//border: 3px solid var(--border-base);
|
||||
}
|
||||
|
||||
.notice .title {
|
||||
content: "NOTE";
|
||||
//position: absolute;
|
||||
border-radius: 12px;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.notice.notice-success{
|
||||
background: var(--suc20);
|
||||
}
|
||||
|
||||
.notice.notice-error{
|
||||
background: var(--err10);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
.pagination {
|
||||
margin: 20px auto 10px ;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
|
||||
|
||||
a,span{
|
||||
font-size: 14px;
|
||||
border-radius: 12px;
|
||||
padding: 4px 18px;
|
||||
background: var(--p20);
|
||||
|
||||
&:hover{
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
&.active {
|
||||
span{
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
.preview-file,.preview-reference{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
background: var(--p10);
|
||||
border-radius: 12px;
|
||||
|
||||
&.is-trashed{
|
||||
border: 2px solid var(--err10);
|
||||
background: var(--p20);
|
||||
}
|
||||
.trashed-text{
|
||||
background: var(--err10);
|
||||
font-size: 12px;
|
||||
padding:2px 10px;
|
||||
}
|
||||
|
||||
.image{
|
||||
|
||||
|
||||
display: flex;
|
||||
|
||||
}
|
||||
|
||||
.reference-action{
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background: var(--p30);
|
||||
.reference-action{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-preview-small{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
border-radius: 12px;
|
||||
padding: 4px;
|
||||
//background: var(--p10);
|
||||
}
|
||||
|
||||
|
||||
.preview-reference{
|
||||
background: var(--p10);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.sortable-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.sortable-ghost{
|
||||
border: 2px dashed var(--p60);
|
||||
}
|
||||
|
||||
.sortable-drag { opacity: 0 !important; } .sortable-ghost { opacity: 1 !important; }
|
||||
@@ -0,0 +1,147 @@
|
||||
.record-edit {
|
||||
position: relative;
|
||||
max-width: 900px;
|
||||
.invalid-feedback {
|
||||
color: var(--text-error);
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.record-header {
|
||||
margin: 10px 0 0;
|
||||
|
||||
.schema-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.record-title {
|
||||
font-size: 18px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.tools-header {
|
||||
margin: 30px 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
padding: 10px;
|
||||
border-radius: 12px;
|
||||
background: var(--p20);
|
||||
}
|
||||
|
||||
.editor-field {
|
||||
background: var(--p20);
|
||||
padding: 18px;
|
||||
position: relative;
|
||||
border-radius: 12px;
|
||||
margin: 6px 0;
|
||||
border-color: transparent;
|
||||
|
||||
.button:not(.primary) {
|
||||
background: var(--p30);
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
|
||||
dialog {
|
||||
.button:not(.primary) {
|
||||
background: var(--p20);
|
||||
|
||||
|
||||
&:hover {
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.field-header {
|
||||
margin-bottom: 4px;
|
||||
position: relative;
|
||||
|
||||
.labels {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label-and-help {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
font-size: 14px;
|
||||
line-height: 14px
|
||||
}
|
||||
|
||||
code {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.system-help-text {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.field-checkbox {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
|
||||
.form-check-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.form-check-label {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.record-edit-file-preview {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
|
||||
.file-details {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
}
|
||||
|
||||
.file-details-item {
|
||||
.text-muted {
|
||||
color: var(--grey-dark);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
.reference-tags {
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
|
||||
.reference-tags-option {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 3px 10px;
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
.reference-tags-results {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.reference-tags-selected-value {
|
||||
font-size: 13px;
|
||||
margin-top: 10px;
|
||||
border-radius: 12px;
|
||||
background: var(--p30);
|
||||
padding: 3px 10px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
line-height: 22px;
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
|
||||
.reference-tags-results {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
border-radius: 12px;
|
||||
z-index: 20;
|
||||
background: var(--p30);
|
||||
//border: 2px solid var(--background-2);
|
||||
transition: 600ms;
|
||||
flex-grow: 1;
|
||||
top: 45px;
|
||||
width: 100%;
|
||||
|
||||
.start-typing {
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
1. Use a more-intuitive box-sizing model.
|
||||
*/
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/*
|
||||
2. Remove default margin
|
||||
*/
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
/*
|
||||
Typographic tweaks!
|
||||
3. Add accessible line-height
|
||||
4. Improve text rendering
|
||||
*/
|
||||
body {
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
/*
|
||||
5. Improve media defaults
|
||||
*/
|
||||
img, picture, video, canvas, svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
/*
|
||||
6. Remove built-in form typography styles
|
||||
*/
|
||||
input, button, textarea, select {
|
||||
font: inherit;
|
||||
}
|
||||
/*
|
||||
7. Avoid text overflows
|
||||
*/
|
||||
p, h1, h2, h3, h4, h5, h6 {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
/*
|
||||
8. Create a root stacking context
|
||||
*/
|
||||
#root, #__next {
|
||||
isolation: isolate;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
.revisions{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
.revision{
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
background: var(--p20);
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
|
||||
.version{
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
&.active{
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selected-revision{
|
||||
margin-top: 30px;
|
||||
align-items: center;
|
||||
background: var(--p20);
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
|
||||
.button{
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
.revision-field{
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
padding: 20px 0;
|
||||
border-bottom: 1px solid var(--p30);
|
||||
flex: 1;
|
||||
.compare-left{
|
||||
width: 45%;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
background: var(--p30);
|
||||
}
|
||||
.compare-right{
|
||||
width: 45%;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
background: var(--p30);
|
||||
}
|
||||
.compare-center{
|
||||
|
||||
width: 10%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.reference-field{
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.revision-references{
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
padding: 20px 0;
|
||||
border-bottom: 1px solid var(--p30);
|
||||
}
|
||||
|
||||
.reference-compare{
|
||||
|
||||
width: 45%;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
background: var(--p30);
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
.tiptap {
|
||||
width: 100%;
|
||||
background: var(--p20);
|
||||
border: 1px solid var(--p50);
|
||||
border-radius: 0 0 5px 5px;
|
||||
padding: 15px 15px;
|
||||
font-size: 16px;
|
||||
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
&:focus {
|
||||
background: var(--p10);
|
||||
|
||||
}
|
||||
|
||||
img {
|
||||
&.ProseMirror-selectednode {
|
||||
box-shadow: 0 0 1px 2px var(--p70);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.editor-field {
|
||||
.editor-toolbar {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
background: var(--p30);
|
||||
border-radius: 5px 5px 0 0;
|
||||
padding: 5px 7px;
|
||||
|
||||
.button:not(.primary) {
|
||||
font-weight: 700;
|
||||
|
||||
&.active {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.tiptap {
|
||||
li > p {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trix-editor {
|
||||
background: var(--p20)!important;
|
||||
border: 1px solid var(--p50)!important;
|
||||
border-radius: 0 0 5px 5px!important;
|
||||
padding: 15px 15px!important;
|
||||
& > div {
|
||||
margin-bottom: 14px;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: var(--p10)!important;
|
||||
|
||||
}
|
||||
figure.attachment{
|
||||
display: flex!important;
|
||||
flex-direction: column!important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.attachment {
|
||||
background: var(--p20);
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[data-trix-mutable].attachment img {
|
||||
box-shadow: 0 0 1px 2px var(--p70) !important;
|
||||
|
||||
}
|
||||
|
||||
.trix-button--remove {
|
||||
box-shadow: none !important;
|
||||
border: 2px solid var(--p40) !important;
|
||||
}
|
||||
|
||||
.trix-button--remove:hover {
|
||||
border: 2px solid var(--p40);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--p80);
|
||||
}
|
||||
}
|
||||
|
||||
trix-toolbar {
|
||||
.trix-button-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.trix-button-group {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
display: flex !important;
|
||||
gap: 4px;
|
||||
}
|
||||
.trix-button-group--history-tools,.trix-button-group--file-tools
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.trix-button {
|
||||
border-radius: 6px !important;
|
||||
background: var(--p30) !important;
|
||||
padding: 14px 22px !important;
|
||||
margin: 0 !important;
|
||||
cursor: pointer;
|
||||
border: 0px solid var(--p30) !important;
|
||||
font-size: 14px !important;
|
||||
min-height: 27px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
gap: 4px;
|
||||
color: var(--text) !important;
|
||||
|
||||
&:before{
|
||||
background-size: 22px!important;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background: var(--p40) !important;
|
||||
}
|
||||
&.trix-active{
|
||||
background: var(--p50) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
.sidebar-top{
|
||||
border: 0px solid var(--p30);
|
||||
font-size: 18px;
|
||||
padding: 20px 20px ;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: var(--p20);
|
||||
margin-bottom: 15px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
//border: 1px solid var(--border-context);
|
||||
border-radius: 12px;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
padding: 20px;
|
||||
background: var(--p20);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
}
|
||||
.sidebar-folder{
|
||||
width: 100%;
|
||||
margin: 3px 12px 3px;
|
||||
.sidebar-folder{
|
||||
margin-left: 5px;
|
||||
|
||||
}
|
||||
}
|
||||
.sidebar-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--p30);
|
||||
font-size: 16px;
|
||||
padding: 3px 12px 3px;
|
||||
|
||||
color: var(--text);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
&:focus{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
|
||||
color: var(--text);
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
padding: 3px 12px;
|
||||
text-decoration: none;
|
||||
transition: 600ms;
|
||||
border-radius: 12px;
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
|
||||
.top-nav{
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.top-nav-item{
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
background: var(--p20);
|
||||
padding: 3px 10px ;
|
||||
&:hover {
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
input.switch {
|
||||
-webkit-appearance: none;
|
||||
width: 34px;
|
||||
height: 18px;
|
||||
border: 1px solid var(--p40);
|
||||
position: relative;
|
||||
border-radius: 50px;
|
||||
box-sizing: content-box;
|
||||
cursor: pointer;
|
||||
transition: background 150ms ease-in-out;
|
||||
background: white;
|
||||
}
|
||||
|
||||
input.switch::after {
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
transition: left 150ms ease-in-out;
|
||||
content: " ";
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: var(--p40);
|
||||
box-shadow: inset 0 0 0px 1px var(--p40);
|
||||
position: absolute;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
input.switch:checked {
|
||||
background: var(--p50);
|
||||
}
|
||||
|
||||
input.switch:checked::after {
|
||||
left: calc(100% - 17px);
|
||||
background: var(--p10);
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
.table {
|
||||
min-width: 600px;
|
||||
overflow: auto;
|
||||
background: var(--p20);
|
||||
padding: 1px;
|
||||
font-size: 14px;
|
||||
border-radius: 12px;
|
||||
|
||||
table {
|
||||
background: var(--p20);
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border: none;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
thead {
|
||||
border-radius: 12px;
|
||||
|
||||
tr {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
max-width: 400px;
|
||||
border: none;
|
||||
background: var(--p20);
|
||||
text-align: left;
|
||||
padding: 8px 16px;
|
||||
|
||||
&.is-sort {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-radius: 12px 0 0 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 12px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
max-width: 400px;
|
||||
height: 48px;
|
||||
padding: 4px 16px;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
//img{
|
||||
// width: 48px;
|
||||
//}
|
||||
|
||||
.status {
|
||||
color: var(--text);
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.row-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.title-td-contents {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
border-radius: 12px;
|
||||
background: var(--p10);
|
||||
border: none;
|
||||
|
||||
&:has(input:checked) {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--p20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tr:nth-child(odd) {
|
||||
//background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
td:nth-child(odd) {
|
||||
// border-left: 1px solid #e4e4e4;
|
||||
// border-right: 1px solid #e4e4e4;
|
||||
}
|
||||
|
||||
th:nth-child(odd) {
|
||||
|
||||
}
|
||||
|
||||
.field-ui-number {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.references{
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
|
||||
.reference{
|
||||
font-size: 13px;
|
||||
border-radius: 12px;
|
||||
background: var(--p30);
|
||||
padding: 1px 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-table-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.tabs{
|
||||
padding: 0;
|
||||
margin: 20px 0 20px;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
.tab{
|
||||
list-style: none;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
.toolbar{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
input.search{
|
||||
border-radius: 12px;
|
||||
background: var(--p20);
|
||||
padding: 4px 10px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
.selected-filter{
|
||||
font-size: 13px;
|
||||
border-radius: 12px;
|
||||
margin: 2px 0;
|
||||
background: var(--p30);
|
||||
padding: 3px 10px;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.filter-input{
|
||||
|
||||
margin: 10px 0 ;
|
||||
input{
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.applied-filter{
|
||||
background: var(--p30);
|
||||
}
|
||||
}
|
||||
.toolbar-filters{ display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;}
|
||||
|
||||
.applied-filters{
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-top: 10px;
|
||||
|
||||
.applied-filter {
|
||||
font-size: 13px;
|
||||
border-radius: 12px;
|
||||
background: var(--p20);
|
||||
padding: 3px 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.applied-filter:hover {
|
||||
background-color: var(--p30);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
.content {
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-family: var(--main-font);
|
||||
color: var(--text);
|
||||
p{
|
||||
|
||||
margin-bottom: 14px;
|
||||
&:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
h1{
|
||||
font-size: 24px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
h2{
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
h3{
|
||||
font-size: 18px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0 0 0 16px;
|
||||
list-style: none outside none;
|
||||
|
||||
li::before {
|
||||
content: "—";
|
||||
opacity: .5;
|
||||
font-size: 12px;
|
||||
padding-right: 6px;
|
||||
vertical-align: 10%;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
code{
|
||||
background: var(--p30);
|
||||
padding: 0 6px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
img{
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
blockquote{
|
||||
border:1px solid var(--p30);
|
||||
border-radius: 12px;
|
||||
padding: 12px 40px;
|
||||
position: relative;
|
||||
|
||||
&::before{
|
||||
content: "\201C";
|
||||
color: var(--p60);
|
||||
font-size:4em;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
&::after{
|
||||
content: '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pre {
|
||||
background: var(--grey-light);
|
||||
border-radius: 0.5rem;
|
||||
color: var(--white);
|
||||
font-family: 'JetBrainsMono', monospace;
|
||||
margin: 1.5rem 0;
|
||||
padding: 0.75rem 1rem;
|
||||
|
||||
code {
|
||||
background: none;
|
||||
color: inherit;
|
||||
font-size: 0.8rem;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.lx-small-text {
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
|
||||
}
|
||||
|
||||
.light-text{
|
||||
color: var(--text-light);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
.wrapper-tiny {
|
||||
background-color: var(--p20);
|
||||
border-radius: 12px;
|
||||
margin: 44px auto;
|
||||
width: 600px;
|
||||
padding: 44px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.common-wrapper {
|
||||
background-color: var(--p20);
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
|
||||
.wrapper-normal {
|
||||
background-color: #fff;
|
||||
border-radius: 32px;
|
||||
margin: 44px auto;
|
||||
width: 1000px;
|
||||
padding: 44px;
|
||||
|
||||
&.transparent {
|
||||
|
||||
margin: 0px auto;
|
||||
padding: 0px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper-large {
|
||||
background-color: #fff;
|
||||
border-radius: 32px;
|
||||
margin: 44px auto;
|
||||
max-width: 1920px;
|
||||
min-width: 1000px;
|
||||
padding: 44px;
|
||||
width: fit-content;
|
||||
&.transparent {
|
||||
padding: 0px;
|
||||
margin: 0px auto;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 1800px) {
|
||||
.wrapper-normal {
|
||||
margin: 0px 0px 0px auto;
|
||||
padding: 20px;
|
||||
|
||||
&.transparent {
|
||||
|
||||
margin: 0px 0px 0px auto;
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper-large {
|
||||
margin: 44px 0px 0px auto;
|
||||
padding: 44px;
|
||||
&.transparent {
|
||||
margin: 0px 0px 0px auto;
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1390px) {
|
||||
|
||||
.wrapper-normal {
|
||||
margin: 0px auto;
|
||||
padding: 20px;
|
||||
|
||||
&.transparent {
|
||||
|
||||
margin: 0px auto;
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper-large {
|
||||
margin: 44px 0px 0px auto;
|
||||
padding: 44px;
|
||||
&.transparent {
|
||||
margin: 0px 0px 0px auto;
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.section-actions {
|
||||
text-align: center;
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.header-normal {
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.header-small {
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
@import "./css/reset.css";
|
||||
@import "./css/helpers.css";
|
||||
@import "./css/notice.css";
|
||||
@import "./css/auth.css";
|
||||
@import "./css/typography.css";
|
||||
@import "./css/sidebar.css";
|
||||
@import "./css/form.css";
|
||||
@import "./css/table.css";
|
||||
@import "./css/avatar.css";
|
||||
@import "./css/codemirror.css";
|
||||
@import "./css/rich.css";
|
||||
@import "./css/layout.css";
|
||||
@import "./css/wrappers.css";
|
||||
@import "./css/toolbar.css";
|
||||
@import "./css/dropdown.css";
|
||||
@import "./css/button.css";
|
||||
@import "./css/checkbox.css";
|
||||
@import "./css/pagination.css";
|
||||
@import "./css/record-edit.css";
|
||||
@import "./css/tabs.css";
|
||||
@import "./css/switch.css";
|
||||
@import "./css/preview.css";
|
||||
@import "./css/dialog.css";
|
||||
@import "./css/autocomplete.css";
|
||||
@import "./css/reference-tags.css";
|
||||
@import "./css/members.css";
|
||||
@import "./css/revisions.css";
|
||||
@import "./css/datepicker.css";
|
||||
|
||||
|
||||
:root {
|
||||
|
||||
--p10: #f4f9ff;
|
||||
--p20: #eaf1f9;
|
||||
--p30: #b3ceff;
|
||||
--p40: #8db5ff;
|
||||
--p50: #70a2ff;
|
||||
--p60: #679cff;
|
||||
--p70: #4284ff;
|
||||
--p80: #1c6bff;
|
||||
--p90: #002b7a;
|
||||
--p100: #000C23;
|
||||
|
||||
|
||||
--suc10: #d1ffb8;
|
||||
--suc20: #d1ffb8;
|
||||
--suc30: #b5ff8d;
|
||||
--suc40: #a2ff70;
|
||||
--suc50: #82cc5a;
|
||||
--suc80: #71b34e;
|
||||
--suc90: #314c22;
|
||||
|
||||
|
||||
|
||||
--err10: #ffb9d0;
|
||||
--err20: #ff9bb3;
|
||||
--err30: #fe7e97;
|
||||
--err40: #de617b;
|
||||
--err50: #be4461;
|
||||
--err80: #61001a;
|
||||
--err90: #560012;
|
||||
|
||||
--grey-dark: #424656;
|
||||
--grey-light: #a6abbd;
|
||||
|
||||
--text: var(--p100);
|
||||
--text-light: var(--grey-dark);
|
||||
--text-error: var(--err50);
|
||||
|
||||
--main-font: ‘Open Sans‘, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
body {
|
||||
background-color: var(--p10);
|
||||
font-family: var(--main-font), sans-serif;
|
||||
color: var(--text);
|
||||
|
||||
:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 1px 2px var(--p70);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-spinner .spinner-border {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn-spinner.spinner-on .spinner-border {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.lucent-component {
|
||||
position: relative;
|
||||
}
|
||||
@@ -7,11 +7,16 @@
|
||||
|
||||
.cm-content{
|
||||
background-color: var(--p10);
|
||||
color: var(--p100);
|
||||
}
|
||||
}
|
||||
|
||||
.cm-content{
|
||||
background-color: var(--p20);
|
||||
|
||||
}
|
||||
.ͼ4 .cm-line ::selection, .ͼ4 .cm-line::selection{
|
||||
background: var(--p40) !important;
|
||||
}
|
||||
|
||||
.cm-activeLine{
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
.flatpickr-wrapper {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.editor-field {
|
||||
.flatpickr-calendar {
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
.flatpickr-months .flatpickr-month {
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flatpickr-current-month .flatpickr-monthDropdown-months {
|
||||
background: var(--p30);
|
||||
}
|
||||
|
||||
.flatpickr-weekdays{
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
|
||||
}
|
||||
|
||||
.flatpickr-weekdaycontainer .flatpickr-weekday{
|
||||
background: var(--p30);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.flatpickr-days{
|
||||
background: var(--p10);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.flatpickr-time{
|
||||
background: var(--p10);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ body:has(dialog[open]) {
|
||||
|
||||
dialog {
|
||||
margin: 2vh auto;
|
||||
background-color: #fff;
|
||||
background-color: var(--p10);
|
||||
padding: 34px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
@@ -49,6 +49,6 @@ dialog::backdrop {
|
||||
position: sticky;
|
||||
top: -34px;
|
||||
z-index: 999;
|
||||
background: #fff;
|
||||
background-color: var(--p10);
|
||||
padding: 10px 0;
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
border-radius: 12px;
|
||||
z-index: 20;
|
||||
z-index: 22;
|
||||
background: var(--p20);
|
||||
transition: 600ms;
|
||||
flex-grow: 1;
|
||||
|
||||
@@ -5,6 +5,17 @@
|
||||
gap: 10px;
|
||||
background: var(--p10);
|
||||
border-radius: 12px;
|
||||
|
||||
&.is-trashed{
|
||||
border: 2px solid var(--err10);
|
||||
background: var(--p20);
|
||||
}
|
||||
.trashed-text{
|
||||
background: var(--err10);
|
||||
font-size: 12px;
|
||||
padding:2px 10px;
|
||||
}
|
||||
|
||||
.image{
|
||||
|
||||
|
||||
@@ -20,7 +31,9 @@
|
||||
&:hover{
|
||||
background: var(--p30);
|
||||
.reference-action{
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.record-edit {
|
||||
position: relative;
|
||||
|
||||
max-width: 900px;
|
||||
.invalid-feedback {
|
||||
color: var(--text-error);
|
||||
font-size: 15px;
|
||||
@@ -44,7 +44,7 @@
|
||||
margin: 6px 0;
|
||||
border-color: transparent;
|
||||
|
||||
.button {
|
||||
.button:not(.primary) {
|
||||
background: var(--p30);
|
||||
|
||||
&:hover {
|
||||
@@ -53,9 +53,10 @@
|
||||
}
|
||||
|
||||
dialog {
|
||||
.button {
|
||||
.button:not(.primary) {
|
||||
background: var(--p20);
|
||||
|
||||
|
||||
&:hover {
|
||||
background: var(--p30);
|
||||
}
|
||||
@@ -143,3 +144,4 @@
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
.tiptap {
|
||||
width: 100%;
|
||||
background: var(--p20);
|
||||
border: 1px solid var(--p50);
|
||||
border-radius: 0 0 5px 5px;
|
||||
padding: 15px 15px;
|
||||
font-size: 16px;
|
||||
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
&:focus {
|
||||
background: var(--p10);
|
||||
|
||||
}
|
||||
|
||||
img {
|
||||
&.ProseMirror-selectednode {
|
||||
box-shadow: 0 0 1px 2px var(--p70);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.editor-field {
|
||||
.editor-toolbar {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
background: var(--p30);
|
||||
border-radius: 5px 5px 0 0;
|
||||
padding: 5px 7px;
|
||||
|
||||
.button:not(.primary) {
|
||||
font-weight: 700;
|
||||
|
||||
&.active {
|
||||
background: var(--p40);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.tiptap {
|
||||
li > p {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trix-editor {
|
||||
background: var(--p20)!important;
|
||||
border: 1px solid var(--p50)!important;
|
||||
border-radius: 0 0 5px 5px!important;
|
||||
padding: 15px 15px!important;
|
||||
& > div {
|
||||
margin-bottom: 14px;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: var(--p10)!important;
|
||||
|
||||
}
|
||||
figure.attachment{
|
||||
display: flex!important;
|
||||
flex-direction: column!important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.attachment {
|
||||
background: var(--p20);
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[data-trix-mutable].attachment img {
|
||||
box-shadow: 0 0 1px 2px var(--p70) !important;
|
||||
|
||||
}
|
||||
|
||||
.trix-button--remove {
|
||||
box-shadow: none !important;
|
||||
border: 2px solid var(--p40) !important;
|
||||
}
|
||||
|
||||
.trix-button--remove:hover {
|
||||
border: 2px solid var(--p40);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--p80);
|
||||
}
|
||||
}
|
||||
|
||||
trix-toolbar {
|
||||
.trix-button-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.trix-button-group {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
display: flex !important;
|
||||
gap: 4px;
|
||||
}
|
||||
.trix-button-group--history-tools,.trix-button-group--file-tools
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.trix-button {
|
||||
border-radius: 6px !important;
|
||||
background: var(--p30) !important;
|
||||
padding: 14px 22px !important;
|
||||
margin: 0 !important;
|
||||
cursor: pointer;
|
||||
border: 0px solid var(--p30) !important;
|
||||
font-size: 14px !important;
|
||||
min-height: 27px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
gap: 4px;
|
||||
color: var(--text) !important;
|
||||
|
||||
&:before{
|
||||
background-size: 22px!important;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background: var(--p40) !important;
|
||||
}
|
||||
&.trix-active{
|
||||
background: var(--p50) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,18 +21,31 @@
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
}
|
||||
.sidebar-folder{
|
||||
width: 100%;
|
||||
margin: 3px 12px 3px;
|
||||
.sidebar-folder{
|
||||
margin-left: 5px;
|
||||
|
||||
}
|
||||
}
|
||||
.sidebar-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--p30);
|
||||
font-size: 16px;
|
||||
padding: 3px 12px 6px;
|
||||
padding: 3px 12px 3px;
|
||||
|
||||
color: var(--text);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
&:focus{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
background: var(--p40);
|
||||
|
||||
@@ -113,6 +113,18 @@
|
||||
.field-ui-number {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.references{
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
|
||||
.reference{
|
||||
font-size: 13px;
|
||||
border-radius: 12px;
|
||||
background: var(--p30);
|
||||
padding: 1px 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-table-row {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user