removed lodash and axios
This commit is contained in:
@@ -83,3 +83,74 @@ export function apiGet(url, options = {}) {
|
||||
},
|
||||
}).then((r) => r.json());
|
||||
}
|
||||
|
||||
export function isEqual(db, ed) {
|
||||
let isObject = (x) =>
|
||||
typeof x === "object" && !Array.isArray(x) && x !== null;
|
||||
let isArray = (x) => x?.constructor === Array;
|
||||
let isEmpty = (x) => x === null || x === undefined || x == [];
|
||||
const db_value = db ?? null;
|
||||
const ed_value = ed ?? null;
|
||||
|
||||
if (isObject(db_value)) {
|
||||
let keys = Object.keys(db_value);
|
||||
return keys.reduce((acc, k) => {
|
||||
if (acc === false) {
|
||||
return false;
|
||||
}
|
||||
return isEqual(db_value?.[k], ed_value?.[k]);
|
||||
}, true);
|
||||
}
|
||||
if (isArray(db_value)) {
|
||||
return db_value.reduce((c, v, i) => {
|
||||
if (c === false) {
|
||||
return false;
|
||||
}
|
||||
return isEqual(v, ed_value?.[i]);
|
||||
}, true);
|
||||
}
|
||||
|
||||
if (isEmpty(db_value) && isEmpty(ed_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (db_value == ed_value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
// const ok = Object.keys,
|
||||
// tx = typeof x,
|
||||
// ty = typeof y;
|
||||
// return x && y && tx === "object" && tx === ty
|
||||
// ? ok(x).length === ok(y).length &&
|
||||
// ok(x).every((key) => isEqual(x[key], y[key]))
|
||||
// : x === y;
|
||||
}
|
||||
|
||||
export function debounce(fn, delay) {
|
||||
let timer;
|
||||
return (...args) => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => fn(...args), delay);
|
||||
};
|
||||
}
|
||||
|
||||
export function arrayUnique(array) {
|
||||
return array.filter((value, index) => array.indexOf(value) === index);
|
||||
}
|
||||
|
||||
export function arrayUniqueBy(items, uniqueBy) {
|
||||
const ids = new Set(items.map((item) => item[uniqueBy]));
|
||||
return [...ids].map((id) => items.find((i) => i[uniqueBy] === id));
|
||||
}
|
||||
export function arrayUniqueCb(items, aFilter) {
|
||||
const cache = new Set();
|
||||
return items.filter((item) => {
|
||||
const cacheValue = aFilter(item);
|
||||
if (cache.has(cacheValue)) return false;
|
||||
cache.add(cacheValue);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,10 +25,8 @@
|
||||
// export let layout;
|
||||
export let channel;
|
||||
|
||||
export let axios;
|
||||
export let readableSchemas;
|
||||
|
||||
setContext("axios", axios);
|
||||
setContext("channel", channel);
|
||||
setContext(
|
||||
"readableSchemas",
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
import ErrorAlert from "../common/ErrorAlert.svelte";
|
||||
import SpinnerButton from "../common/SpinnerButton.svelte";
|
||||
import Avatar from "./Avatar.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import { getContext } from "svelte";
|
||||
import SuccessAlert from "../common/SuccessAlert.svelte";
|
||||
import { apiPost } from "../../helpers";
|
||||
|
||||
const user = getContext("user");
|
||||
const channel = getContext("channel");
|
||||
@@ -16,16 +17,15 @@
|
||||
e.preventDefault();
|
||||
errorMessage = "";
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/account/update-name", {
|
||||
name: name,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/account/update-name", {
|
||||
name: name,
|
||||
})
|
||||
.then((response) => {
|
||||
successAlert.show();
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data.error;
|
||||
console.log({errorMessage});
|
||||
console.log({ errorMessage });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,55 +33,55 @@
|
||||
e.preventDefault();
|
||||
errorMessage = "";
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/account/update-email", {
|
||||
email: email,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/account/update-email", {
|
||||
email: email,
|
||||
})
|
||||
.then((response) => {
|
||||
successAlert.show();
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data.error;
|
||||
console.log({errorMessage});
|
||||
console.log({ errorMessage });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<div class="wrapper-tiny">
|
||||
<ErrorAlert message={errorMessage}/>
|
||||
<ErrorAlert message={errorMessage} />
|
||||
<SuccessAlert bind:this={successAlert} />
|
||||
<h3 class="header-small mb-5">
|
||||
<Avatar name={user.name}/>
|
||||
<Avatar name={user.name} />
|
||||
</h3>
|
||||
<form on:submit={saveName}>
|
||||
<div class="input-group mb-5">
|
||||
<input
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control mb-3"
|
||||
placeholder="Name"
|
||||
required
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control mb-3"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<SpinnerButton label="Update Name"/>
|
||||
<SpinnerButton label="Update Name" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form on:submit={saveEmail}>
|
||||
<div class="input-group mb-5">
|
||||
<input
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control mb-3"
|
||||
placeholder="Email"
|
||||
required
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control mb-3"
|
||||
placeholder="Email"
|
||||
required
|
||||
/>
|
||||
<SpinnerButton label="Update Email"/>
|
||||
<SpinnerButton label="Update Email" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" href="{ channel.lucentUrl }/logout">Logout from this
|
||||
device</a>
|
||||
<a
|
||||
class="list-group-item list-group-item-action"
|
||||
href="{channel.lucentUrl}/logout">Logout from this device</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script>
|
||||
import { apiPost } from "../../helpers";
|
||||
import ErrorAlert from "../common/ErrorAlert.svelte";
|
||||
import SpinnerButton from "../common/SpinnerButton.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import { getContext } from "svelte";
|
||||
|
||||
const channel = getContext("channel");
|
||||
let name = "";
|
||||
@@ -12,48 +13,45 @@
|
||||
e.preventDefault();
|
||||
errorMessage = "";
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/register", {
|
||||
name: name,
|
||||
email: email,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/register", {
|
||||
name: name,
|
||||
email: email,
|
||||
})
|
||||
.then(() => {
|
||||
window.location = channel.lucentUrl + "/login";
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data.error;
|
||||
console.log({errorMessage});
|
||||
console.log({ errorMessage });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="wrapper-tiny">
|
||||
<ErrorAlert message={errorMessage}/>
|
||||
<ErrorAlert message={errorMessage} />
|
||||
|
||||
<form on:submit={register}>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control"
|
||||
id="name"
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control"
|
||||
id="name"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control"
|
||||
id="email"
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control"
|
||||
id="email"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="text-center mt-5 d-block">
|
||||
<SpinnerButton label="Register"/>
|
||||
<SpinnerButton label="Register" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/* eslint-disable no-undefined,no-param-reassign,no-shadow */
|
||||
|
||||
/**
|
||||
* Throttle execution of a function. Especially useful for rate limiting
|
||||
* execution of handlers on events like resize and scroll.
|
||||
*
|
||||
* @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)
|
||||
* are most useful.
|
||||
* @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,
|
||||
* as-is, to `callback` when the throttled-function is executed.
|
||||
* @param {object} [options] - An object to configure options.
|
||||
* @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds
|
||||
* while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed
|
||||
* one final time after the last throttled-function call. (After the throttled-function has not been called for
|
||||
* `delay` milliseconds, the internal counter is reset).
|
||||
* @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback
|
||||
* immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that
|
||||
* callback will never executed if both noLeading = true and noTrailing = true.
|
||||
* @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is
|
||||
* false (at end), schedule `callback` to execute after `delay` ms.
|
||||
*
|
||||
* @returns {Function} A new, throttled, function.
|
||||
*/
|
||||
export function throttle(delay, callback, options) {
|
||||
const {
|
||||
noTrailing = false,
|
||||
noLeading = false,
|
||||
debounceMode = undefined,
|
||||
} = options || {};
|
||||
/*
|
||||
* After wrapper has stopped being called, this timeout ensures that
|
||||
* `callback` is executed at the proper times in `throttle` and `end`
|
||||
* debounce modes.
|
||||
*/
|
||||
let timeoutID;
|
||||
let cancelled = false;
|
||||
|
||||
// Keep track of the last time `callback` was executed.
|
||||
let lastExec = 0;
|
||||
|
||||
// Function to clear existing timeout
|
||||
function clearExistingTimeout() {
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to cancel next exec
|
||||
function cancel(options) {
|
||||
const { upcomingOnly = false } = options || {};
|
||||
clearExistingTimeout();
|
||||
cancelled = !upcomingOnly;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `wrapper` function encapsulates all of the throttling / debouncing
|
||||
* functionality and when executed will limit the rate at which `callback`
|
||||
* is executed.
|
||||
*/
|
||||
function wrapper(...arguments_) {
|
||||
let self = this;
|
||||
let elapsed = Date.now() - lastExec;
|
||||
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute `callback` and update the `lastExec` timestamp.
|
||||
function exec() {
|
||||
lastExec = Date.now();
|
||||
callback.apply(self, arguments_);
|
||||
}
|
||||
|
||||
/*
|
||||
* If `debounceMode` is true (at begin) this is used to clear the flag
|
||||
* to allow future `callback` executions.
|
||||
*/
|
||||
function clear() {
|
||||
timeoutID = undefined;
|
||||
}
|
||||
|
||||
if (!noLeading && debounceMode && !timeoutID) {
|
||||
/*
|
||||
* Since `wrapper` is being called for the first time and
|
||||
* `debounceMode` is true (at begin), execute `callback`
|
||||
* and noLeading != true.
|
||||
*/
|
||||
exec();
|
||||
}
|
||||
|
||||
clearExistingTimeout();
|
||||
|
||||
if (debounceMode === undefined && elapsed > delay) {
|
||||
if (noLeading) {
|
||||
/*
|
||||
* In throttle mode with noLeading, if `delay` time has
|
||||
* been exceeded, update `lastExec` and schedule `callback`
|
||||
* to execute after `delay` ms.
|
||||
*/
|
||||
lastExec = Date.now();
|
||||
if (!noTrailing) {
|
||||
timeoutID = setTimeout(debounceMode ? clear : exec, delay);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* In throttle mode without noLeading, if `delay` time has been exceeded, execute
|
||||
* `callback`.
|
||||
*/
|
||||
exec();
|
||||
}
|
||||
} else if (noTrailing !== true) {
|
||||
/*
|
||||
* In trailing throttle mode, since `delay` time has not been
|
||||
* exceeded, schedule `callback` to execute `delay` ms after most
|
||||
* recent execution.
|
||||
*
|
||||
* If `debounceMode` is true (at begin), schedule `clear` to execute
|
||||
* after `delay` ms.
|
||||
*
|
||||
* If `debounceMode` is false (at end), schedule `callback` to
|
||||
* execute after `delay` ms.
|
||||
*/
|
||||
timeoutID = setTimeout(
|
||||
debounceMode ? clear : exec,
|
||||
debounceMode === undefined ? delay - elapsed : delay,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.cancel = cancel;
|
||||
|
||||
// Return the wrapper function.
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
export function debounce(delay, callback, options) {
|
||||
const { atBegin = false } = options || {};
|
||||
return throttle(delay, callback, { debounceMode: atBegin !== false });
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import {getContext, onMount} from "svelte";
|
||||
import axios from "axios";
|
||||
|
||||
import { getContext, onMount } from "svelte";
|
||||
import { apiPost } from "../../helpers";
|
||||
const channel = getContext("channel");
|
||||
export let title;
|
||||
export let command;
|
||||
@@ -12,59 +11,57 @@
|
||||
let inProgress = false;
|
||||
|
||||
function connect() {
|
||||
const eventSource = new EventSource(channel.lucentUrl + "/command-report-source/" + command.signature );
|
||||
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()
|
||||
}
|
||||
anchorEl.scrollIntoView();
|
||||
};
|
||||
eventSource.onerror = (e) => {
|
||||
console.log(e)
|
||||
console.log(e);
|
||||
eventSource.close();
|
||||
inProgress = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildWebsite(e) {
|
||||
e.preventDefault();
|
||||
inProgress = true;
|
||||
axios.post(channel.lucentUrl + "/command/" + command.signature).then(response => {
|
||||
connect()
|
||||
})
|
||||
|
||||
apiPost(channel.lucentUrl + "/command/" + command.signature).then(
|
||||
(response) => {
|
||||
connect();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
connect()
|
||||
})
|
||||
|
||||
connect();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="common-wrapper">
|
||||
<div class="lx-card mt-5">
|
||||
|
||||
<h3 class="header-small mb-5">{title}</h3>
|
||||
|
||||
<button on:click={buildWebsite} class="button primary mb-3" disabled={inProgress}>Start
|
||||
<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">
|
||||
Action in progress
|
||||
</span>
|
||||
<span class="badge text-bg-warning"> Action in progress </span>
|
||||
{/if}
|
||||
{#if !inProgress && logs}
|
||||
<span class="badge text-bg-info">
|
||||
Action completed
|
||||
</span>
|
||||
<span class="badge text-bg-info"> Action completed </span>
|
||||
{/if}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<pre class="logs">{logs}
|
||||
@@ -72,12 +69,13 @@
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.logs{
|
||||
.logs {
|
||||
max-height: 70vh;
|
||||
overflow: scroll;
|
||||
background: var(--p90);
|
||||
color: var(--p10);
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
import { range } from "lodash";
|
||||
|
||||
import NavItem from "./NavItem.svelte";
|
||||
export let inModal;
|
||||
export let modalUrl;
|
||||
@@ -11,7 +11,11 @@
|
||||
|
||||
$: totalPages = Math.ceil(total / limit);
|
||||
$: currentPage = Math.ceil((skip - 1) / limit) + 1;
|
||||
|
||||
const range = (start, end, step = 1) =>
|
||||
Array.from(
|
||||
{ length: Math.ceil((end - start) / step) },
|
||||
(_, i) => start + i * step,
|
||||
);
|
||||
$: pageRange = range(currentPage - 3, currentPage + 4).filter((i) => {
|
||||
return i > 0 && i <= totalPages;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
import { debounce } from "lodash";
|
||||
import { apiGet, debounce } from "../../../helpers";
|
||||
|
||||
const channel = getContext("channel");
|
||||
const dispatch = createEventDispatcher();
|
||||
@@ -12,17 +12,16 @@
|
||||
$: searchOptions = [];
|
||||
|
||||
const updateResults = debounce((e) => {
|
||||
axios
|
||||
.get(channel.lucentUrl + "/records/suggestions", {
|
||||
params: {
|
||||
schema: field.collections[0],
|
||||
field: "search",
|
||||
value: search,
|
||||
ui: "search",
|
||||
},
|
||||
})
|
||||
apiGet(channel.lucentUrl + "/records/suggestions", {
|
||||
params: {
|
||||
schema: field.collections[0],
|
||||
field: "search",
|
||||
value: search,
|
||||
ui: "search",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
searchOptions = response.data;
|
||||
searchOptions = response;
|
||||
})
|
||||
.catch((error) => {
|
||||
searchOptions = [];
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
<script>
|
||||
import {onDestroy, onMount} from "svelte";
|
||||
|
||||
import tinymce from "tinymce/tinymce";
|
||||
import "tinymce/models/dom";
|
||||
import "tinymce/icons/default";
|
||||
import "tinymce/themes/silver";
|
||||
import "tinymce/skins/ui/oxide/skin.css";
|
||||
import contentUiSkinCss from "tinymce/skins/ui/oxide/content.css?inline";
|
||||
import customcss from "./tinymce.css?inline";
|
||||
|
||||
import "tinymce/plugins/link";
|
||||
import "tinymce/plugins/code";
|
||||
import "tinymce/plugins/image";
|
||||
import "tinymce/plugins/table";
|
||||
import "tinymce/plugins/codesample";
|
||||
import "tinymce/plugins/media";
|
||||
|
||||
import "tinymce/plugins/lists";
|
||||
import "tinymce/plugins/autoresize";
|
||||
import "tinymce/plugins/wordcount";
|
||||
|
||||
export let value = "";
|
||||
export let additionalConfig = {};
|
||||
let lastVal = "";
|
||||
let textareaEl;
|
||||
let activeEditor;
|
||||
let editorWrapper;
|
||||
const plugins = [
|
||||
"autoresize",
|
||||
"code",
|
||||
"image",
|
||||
"table",
|
||||
"codesample",
|
||||
"link",
|
||||
"lists",
|
||||
"media",
|
||||
"wordcount",
|
||||
];
|
||||
const toolbar =
|
||||
"bold italic underline strikethrough removeformat | link | subscript superscript bullist numlist media image codesample table code wordcount blockquote indent outdent blocks";
|
||||
|
||||
onDestroy(() => {
|
||||
if (activeEditor) {
|
||||
activeEditor.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
const config = {
|
||||
target: textareaEl,
|
||||
toolbar_mode: "sliding",
|
||||
toolbar_sticky: true,
|
||||
skin: false,
|
||||
content_css: false,
|
||||
content_style: contentUiSkinCss.toString() + customcss.toString(),
|
||||
branding: false,
|
||||
inline: false,
|
||||
plugins: plugins,
|
||||
contextmenu: false,
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
entity_encoding: "raw",
|
||||
convert_urls: false,
|
||||
toolbar: toolbar,
|
||||
image_caption: true,
|
||||
relative_urls: false,
|
||||
browser_spellcheck: true,
|
||||
max_height: 600,
|
||||
// media_poster: false,
|
||||
|
||||
setup: function (editor) {
|
||||
activeEditor = editor;
|
||||
|
||||
editor.on("init", function (e) {
|
||||
editor.setContent(value ?? "");
|
||||
});
|
||||
|
||||
// editor.on("blur", function (e) {
|
||||
// let content = setImageDimensions(editor.getContent());
|
||||
// dispatch("editorBlur", content);
|
||||
// editorWrapper.classList.remove("editorFocus");
|
||||
// // return false;
|
||||
// });
|
||||
|
||||
// editor.on("focus", function (e) {
|
||||
// editorWrapper.classList.add("editorFocus");
|
||||
// // return false;
|
||||
// });
|
||||
|
||||
editor.on("change input undo redo", function (e) {
|
||||
lastVal = editor.getContent();
|
||||
if (lastVal !== value) {
|
||||
value = lastVal;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
tinymce.init({...config, ...additionalConfig});
|
||||
});
|
||||
|
||||
export function insertMedia(info){
|
||||
activeEditor.execCommand('InsertHTML', false, info.html);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={editorWrapper} class="tox-wrapper">
|
||||
<div class="form-control" bind:this={textareaEl}>
|
||||
{@html value}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(.tox:not(.tox-tinymce-inline) .tox-editor-header) {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ced4da;
|
||||
box-shadow: none;
|
||||
padding: 4px 0;
|
||||
transition: box-shadow 0.5s;
|
||||
}
|
||||
|
||||
:global(.tox-tinymce) {
|
||||
border: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
.mce-content-body .img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.mce-content-body{
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.mce-content-body p{
|
||||
|
||||
margin-bottom: 14px;
|
||||
&:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mce-content-body ul {
|
||||
padding: 0 0 0 16px;
|
||||
list-style: none outside none;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.mce-content-body li::before {
|
||||
content: "—";
|
||||
opacity: .5;
|
||||
font-size: 12px;
|
||||
padding-right: 6px;
|
||||
vertical-align: 10%;
|
||||
}
|
||||
|
||||
.mce-content-body li {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -3,9 +3,8 @@
|
||||
import SuccessAlert from "../common/SuccessAlert.svelte";
|
||||
import SpinnerButton from "../common/SpinnerButton.svelte";
|
||||
import MemberSettingsCard from "./MemberSettingsCard.svelte";
|
||||
import {getContext} from "svelte";
|
||||
import axios from "axios";
|
||||
|
||||
import { getContext } from "svelte";
|
||||
import { apiPost } from "../../helpers";
|
||||
|
||||
const channel = getContext("channel");
|
||||
export let users;
|
||||
@@ -23,15 +22,14 @@
|
||||
function invite(newName, newEmail, newRole) {
|
||||
errorMessage = "";
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/members/invite", {
|
||||
name: newName,
|
||||
email: newEmail,
|
||||
roles: [newRole],
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/members/invite", {
|
||||
name: newName,
|
||||
email: newEmail,
|
||||
roles: [newRole],
|
||||
})
|
||||
.then((response) => {
|
||||
successAlert.show("User was invited");
|
||||
users = [...users, response.data.user];
|
||||
users = [...users, response.user];
|
||||
name = null;
|
||||
email = null;
|
||||
role = null;
|
||||
@@ -45,14 +43,13 @@
|
||||
e.preventDefault();
|
||||
errorMessage = "";
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/members/update", {
|
||||
id: e.detail.user,
|
||||
roles: e.detail.roles,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/members/update", {
|
||||
id: e.detail.user,
|
||||
roles: e.detail.roles,
|
||||
})
|
||||
.then((response) => {
|
||||
successAlert.show("Users updated");
|
||||
users = response.data.users;
|
||||
users = response.users;
|
||||
})
|
||||
.catch((error) => {
|
||||
errorMessage = error.response?.data?.error ?? "";
|
||||
@@ -63,50 +60,45 @@
|
||||
<div class="common-wrapper">
|
||||
<div class="lx-card mt-5">
|
||||
<h3 class="header-small mb-5">Invite people</h3>
|
||||
<ErrorAlert message={errorMessage}/>
|
||||
<SuccessAlert bind:this={successAlert}/>
|
||||
<ErrorAlert message={errorMessage} />
|
||||
<SuccessAlert bind:this={successAlert} />
|
||||
|
||||
<form on:submit={submitInvite}>
|
||||
<div class="mb-3">
|
||||
<label for="inviteeName" class="form-label"
|
||||
>Invitee Name</label
|
||||
>
|
||||
<label for="inviteeName" class="form-label">Invitee Name</label>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control"
|
||||
id="inviteeName"
|
||||
placeholder="Member name"
|
||||
required
|
||||
type="text"
|
||||
bind:value={name}
|
||||
class="form-control"
|
||||
id="inviteeName"
|
||||
placeholder="Member name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="inviteeEmail" class="form-label"
|
||||
>Invitee Email Address</label
|
||||
>Invitee Email Address</label
|
||||
>
|
||||
<input
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control"
|
||||
id="inviteeEmail"
|
||||
placeholder="Member email"
|
||||
required
|
||||
type="email"
|
||||
bind:value={email}
|
||||
class="form-control"
|
||||
id="inviteeEmail"
|
||||
placeholder="Member email"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="me-3">
|
||||
<select bind:value={role}>
|
||||
{#each channel.roles.filter((r) => r !== "removed") as arole}
|
||||
<option
|
||||
value={arole}
|
||||
|
||||
>{arole}</option>
|
||||
<option value={arole}>{arole}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 d-block text-center">
|
||||
<SpinnerButton label="Invite"/>
|
||||
<SpinnerButton label="Invite" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -115,10 +107,10 @@
|
||||
<h3 class="header-small mb-5 mt-5">Members</h3>
|
||||
{#each users as user}
|
||||
<MemberSettingsCard
|
||||
member={user}
|
||||
roles={channel.roles}
|
||||
on:update={update}
|
||||
on:reinvite={(e) => invite(e.detail.email, e.detail.role)}
|
||||
member={user}
|
||||
roles={channel.roles}
|
||||
on:update={update}
|
||||
on:reinvite={(e) => invite(e.detail.email, e.detail.role)}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<script>
|
||||
import { afterUpdate, getContext, onMount } from "svelte";
|
||||
import { isEqual } from "lodash";
|
||||
import axios from "axios";
|
||||
import EditHeader from "./header/EditHeader.svelte";
|
||||
import ContentTabs from "./header/ContentTabs.svelte";
|
||||
import FormField from "./FormField.svelte";
|
||||
@@ -9,6 +7,7 @@
|
||||
import Info from "./Info.svelte";
|
||||
import ErrorAlert from "../common/ErrorAlert.svelte";
|
||||
import Title from "./header/Title.svelte";
|
||||
import { apiPost, isEqual } from "../../helpers";
|
||||
|
||||
const channel = getContext("channel");
|
||||
|
||||
@@ -97,12 +96,11 @@
|
||||
graph.edges = graph.edges?.filter(
|
||||
(edge) => !edge._isTrashed && edge.source === record.id,
|
||||
);
|
||||
axios
|
||||
.post(channel.lucentUrl + "/records", {
|
||||
record: record,
|
||||
edges: graph.edges,
|
||||
isCreateMode: isCreateMode,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/records", {
|
||||
record: record,
|
||||
edges: graph.edges,
|
||||
isCreateMode: isCreateMode,
|
||||
})
|
||||
.then(function (response) {
|
||||
console.log("SAVE: SAVED");
|
||||
|
||||
@@ -110,14 +108,14 @@
|
||||
window.location =
|
||||
channel.lucentUrl + "/records/" + record.id;
|
||||
} else {
|
||||
record = response.data.records[0] ?? null;
|
||||
record = response.records[0] ?? null;
|
||||
if (!record) {
|
||||
// means trashed
|
||||
hasUnsavedData = false;
|
||||
window.location = channel.lucentUrl;
|
||||
return;
|
||||
}
|
||||
graph = response.data;
|
||||
graph = response;
|
||||
setOriginalContent();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { friendlyDate } from "../../helpers";
|
||||
import { friendlyDate, isEqual } 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";
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
onMount,
|
||||
} from "svelte";
|
||||
|
||||
import { isEqual } from "lodash";
|
||||
import FormField from "./FormField.svelte";
|
||||
import FilePreview from "./FilePreview.svelte";
|
||||
import ContentTabs from "./header/ContentTabs.svelte";
|
||||
import ErrorAlert from "../common/ErrorAlert.svelte";
|
||||
import EditHeader from "./header/EditHeader.svelte";
|
||||
import axios from "axios";
|
||||
import Title from "./header/Title.svelte";
|
||||
import { apiPost, isEqual } from "../../helpers";
|
||||
|
||||
const channel = getContext("channel");
|
||||
const dispatch = createEventDispatcher();
|
||||
@@ -118,17 +117,16 @@
|
||||
(edge) => !edge._isTrashed && edge.source === record.id,
|
||||
) ?? [];
|
||||
|
||||
axios
|
||||
.post(channel.lucentUrl + "/records", {
|
||||
record: record,
|
||||
edges: graph.edges,
|
||||
isCreateMode: isCreateMode,
|
||||
})
|
||||
apiPost(channel.lucentUrl + "/records", {
|
||||
record: record,
|
||||
edges: graph.edges,
|
||||
isCreateMode: isCreateMode,
|
||||
})
|
||||
.then(function (response) {
|
||||
console.log("SAVE: SAVED INLINE");
|
||||
|
||||
record = response.data.records[0];
|
||||
graph = response.data;
|
||||
record = response.records[0];
|
||||
graph = response;
|
||||
if (!isCreateMode) {
|
||||
setOriginalContent();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script>
|
||||
import {getContext} from "svelte";
|
||||
import {insertEdges} from "./reference";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
import {sortByField} from "../../edges/sortEdges";
|
||||
import { getContext } from "svelte";
|
||||
import { insertEdges } 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;
|
||||
@@ -15,27 +14,36 @@
|
||||
export let validationErrors;
|
||||
$: 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 =
|
||||
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)) ?? [];
|
||||
|
||||
let collections = channel.schemas.filter((aschema) =>
|
||||
field.collections.includes(aschema.name)
|
||||
field.collections.includes(aschema.name),
|
||||
);
|
||||
|
||||
function removeReference(e) {
|
||||
e.preventDefault();
|
||||
graph.edges = graph.edges.filter(
|
||||
(edge) => !(edge.target === e.detail && edge.field === field.name)
|
||||
(edge) => !(edge.target === e.detail && edge.field === field.name),
|
||||
);
|
||||
}
|
||||
|
||||
function reorder(e) {
|
||||
|
||||
graph.edges = sortByField(e.detail.source, e.detail.target, graph.edges, field.name, references);
|
||||
graph.edges = sortByField(
|
||||
e.detail.source,
|
||||
e.detail.target,
|
||||
graph.edges,
|
||||
field.name,
|
||||
references,
|
||||
);
|
||||
}
|
||||
|
||||
function insert(e) {
|
||||
@@ -49,9 +57,14 @@
|
||||
// }).then(function (response) {
|
||||
// graph = response.data.graph;
|
||||
// })
|
||||
graph = insertEdges(graph, record, e.detail.records, field.name, e.detail.action);
|
||||
graph = insertEdges(
|
||||
graph,
|
||||
record,
|
||||
e.detail.records,
|
||||
field.name,
|
||||
e.detail.action,
|
||||
);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{#if errorMessage}
|
||||
@@ -61,10 +74,10 @@
|
||||
{/if}
|
||||
<div class="inline-card-wrapper">
|
||||
<ReferenceInlineButtons
|
||||
recordId={null}
|
||||
schemas={collections}
|
||||
on:insert={insert}
|
||||
on:save={insert}
|
||||
recordId={null}
|
||||
schemas={collections}
|
||||
on:insert={insert}
|
||||
on:save={insert}
|
||||
/>
|
||||
</div>
|
||||
{#if references.length > 0}
|
||||
@@ -72,10 +85,10 @@
|
||||
{#each references as reference (reference.id)}
|
||||
<div>
|
||||
<PreviewReference
|
||||
{graph}
|
||||
record={reference}
|
||||
hasDelete={true}
|
||||
on:remove={removeReference}
|
||||
{graph}
|
||||
record={reference}
|
||||
hasDelete={true}
|
||||
on:remove={removeReference}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script>
|
||||
import {createEventDispatcher, getContext} from "svelte";
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
import Icon from "../../common/Icon.svelte";
|
||||
import InlineEdit from "../InlineEdit.svelte";
|
||||
import Dialog from "../../dialog/Dialog.svelte";
|
||||
import DialogRecord from "../../dialog/DialogRecord.svelte";
|
||||
import axios from "axios";
|
||||
import Dropdown from "../../common/Dropdown.svelte";
|
||||
import { apiGet } from "../../../helpers";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const channel = getContext("channel");
|
||||
@@ -24,7 +24,7 @@
|
||||
e.preventDefault();
|
||||
console.log("Save inline");
|
||||
inLineCreateRecord = null;
|
||||
dialogRecord.close()
|
||||
dialogRecord.close();
|
||||
dispatch("save", {
|
||||
records: e.detail.records,
|
||||
after: recordId,
|
||||
@@ -44,11 +44,10 @@
|
||||
function createInlineReference(e, schemaUId) {
|
||||
e.preventDefault();
|
||||
inLineCreateRecord = null;
|
||||
axios
|
||||
.get(channel.lucentUrl + "/records/newInline?schema=" + schemaUId)
|
||||
apiGet(channel.lucentUrl + "/records/newInline?schema=" + schemaUId)
|
||||
.then((response) => {
|
||||
inLineCreateRecord = response.data;
|
||||
dialogRecord.open()
|
||||
inLineCreateRecord = response;
|
||||
dialogRecord.open();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
@@ -57,60 +56,53 @@
|
||||
</script>
|
||||
|
||||
{#if schemas.length > 1}
|
||||
<div
|
||||
style="display: flex;align-items: center;gap:4px"
|
||||
>
|
||||
<div style="display: flex;align-items: center;gap:4px">
|
||||
<Dropdown>
|
||||
<div slot="button">New</div>
|
||||
{#each schemas as schema}
|
||||
<button
|
||||
class=" button"
|
||||
on:click={(e) =>
|
||||
createInlineReference(e, schema.name)}
|
||||
>{schema.label}
|
||||
class=" button"
|
||||
on:click={(e) => createInlineReference(e, schema.name)}
|
||||
>{schema.label}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
</Dropdown>
|
||||
<Dropdown>
|
||||
<div slot="button"> <Icon icon="magnifying-glass"/></div>
|
||||
<div slot="button"><Icon icon="magnifying-glass" /></div>
|
||||
{#each schemas as schema}
|
||||
<button
|
||||
class="button"
|
||||
on:click={(e) => openBrowseModal(e, schema.name)}
|
||||
>{schema.label}
|
||||
class="button"
|
||||
on:click={(e) => openBrowseModal(e, schema.name)}
|
||||
>{schema.label}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
</Dropdown>
|
||||
</div>
|
||||
{:else}
|
||||
<div style="display:flex;align-items: center;gap: 4px">
|
||||
<button
|
||||
class="button"
|
||||
on:click={(e) => createInlineReference(e, schemas[0].name)}
|
||||
>New
|
||||
class="button"
|
||||
on:click={(e) => createInlineReference(e, schemas[0].name)}
|
||||
>New
|
||||
</button>
|
||||
<button
|
||||
class="button"
|
||||
on:click={(e) => openBrowseModal(e, schemas[0].name)}
|
||||
>
|
||||
<Icon icon="magnifying-glass"/>
|
||||
</button
|
||||
class="button"
|
||||
on:click={(e) => openBrowseModal(e, schemas[0].name)}
|
||||
>
|
||||
<Icon icon="magnifying-glass" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<DialogRecord bind:this={dialogRecord}>
|
||||
{#if inLineCreateRecord}
|
||||
<InlineEdit
|
||||
{...inLineCreateRecord}
|
||||
isCreateMode={true}
|
||||
on:cancel={(e) => (inLineCreateRecord = null)}
|
||||
on:inlinesaved={save}
|
||||
{...inLineCreateRecord}
|
||||
isCreateMode={true}
|
||||
on:cancel={(e) => (inLineCreateRecord = null)}
|
||||
on:inlinesaved={save}
|
||||
/>
|
||||
|
||||
{/if}
|
||||
</DialogRecord>
|
||||
|
||||
<Dialog bind:this={browseModal} on:insert={insert}/>
|
||||
<Dialog bind:this={browseModal} on:insert={insert} />
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
import { debounce } from "lodash";
|
||||
import { getErrorMessage } from "./errorMessage";
|
||||
import { insertEdges } from "./reference.js";
|
||||
import Icon from "../../common/Icon.svelte";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import Tinymce from "../../libs/Tinymce.svelte";
|
||||
import RichEditorFiles from "./RichEditorFiles.svelte";
|
||||
import {getErrorMessage} from "./errorMessage";
|
||||
import { getErrorMessage } from "./errorMessage";
|
||||
import Trix from "../../libs/Trix.svelte";
|
||||
|
||||
export let value;
|
||||
@@ -18,29 +17,24 @@
|
||||
readonly: field.readonly && !isCreateMode,
|
||||
};
|
||||
|
||||
function insertMedia(e){
|
||||
editor.insertMedia(e.detail)
|
||||
function insertMedia(e) {
|
||||
editor.insertMedia(e.detail);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
|
||||
<Trix {field} bind:this={editor} bind:value></Trix>
|
||||
<!-- <Tinymce bind:this={editor} bind:value {additionalConfig}/>-->
|
||||
<!-- <Tinymce bind:this={editor} bind:value {additionalConfig}/>-->
|
||||
{#if field.collections.length > 0}
|
||||
<RichEditorFiles
|
||||
bind:graph
|
||||
{record}
|
||||
{field}
|
||||
{validationErrors}
|
||||
on:editor-insert={insertMedia}
|
||||
>
|
||||
|
||||
|
||||
</RichEditorFiles>
|
||||
bind:graph
|
||||
{record}
|
||||
{field}
|
||||
{validationErrors}
|
||||
on:editor-insert={insertMedia}
|
||||
></RichEditorFiles>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if errorMessage}
|
||||
<div class="invalid-feedback d-block">
|
||||
{errorMessage}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getContext } from "svelte";
|
||||
import Icon from "../../common/Icon.svelte";
|
||||
import { getErrorMessage } from "./errorMessage";
|
||||
@@ -14,12 +13,11 @@
|
||||
|
||||
function generateId(e) {
|
||||
e.preventDefault();
|
||||
value = uuidv4();
|
||||
value = self.crypto.randomUUID();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<input
|
||||
type="text"
|
||||
@@ -31,13 +29,13 @@
|
||||
{readonly}
|
||||
/>
|
||||
{#if !readonly}
|
||||
<button
|
||||
class="btn btn-primary ms-2"
|
||||
title="Generate a new UUIDv4"
|
||||
on:click={generateId}
|
||||
>
|
||||
<Icon icon="dice" />
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary ms-2"
|
||||
title="Generate a new UUIDv4"
|
||||
on:click={generateId}
|
||||
>
|
||||
<Icon icon="dice" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<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();
|
||||
let id = self.crypto.randomUUID();
|
||||
</script>
|
||||
|
||||
<div class="mb-0">
|
||||
@@ -25,6 +24,6 @@
|
||||
placeholder="https://www.example.com"
|
||||
/>
|
||||
{#if field.help}
|
||||
<small class=" text-primary opacity-50">{field.help}</small>
|
||||
<small class=" text-primary opacity-50">{field.help}</small>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,24 +1,36 @@
|
||||
import {uniqBy} from "lodash";
|
||||
import { arrayUniqueCb } from "../../../helpers";
|
||||
|
||||
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: ""
|
||||
};
|
||||
});
|
||||
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: "",
|
||||
};
|
||||
});
|
||||
|
||||
let replacedEdges = graph.edges;
|
||||
if (action === "replace") {
|
||||
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
|
||||
}
|
||||
let replacedEdges = graph.edges;
|
||||
if (action === "replace") {
|
||||
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);
|
||||
return graph;
|
||||
graph.records = arrayUniqueCb(
|
||||
[...graph.records, ...targetRecords],
|
||||
(r) => r.id,
|
||||
);
|
||||
graph.edges = arrayUniqueCb(
|
||||
[...replacedEdges, ...newEdges],
|
||||
(edge) => edge.source + edge.target + edge.field + edge.depth,
|
||||
);
|
||||
return graph;
|
||||
}
|
||||
|
||||
Generated
+1695
-4376
File diff suppressed because it is too large
Load Diff
+27
-32
@@ -1,34 +1,29 @@
|
||||
{
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/commands": "^6.6.0",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.2.5",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||
"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",
|
||||
"npm": "^10.8.2",
|
||||
"postcss": "8.4.31",
|
||||
"sass": "^1.77.8",
|
||||
"sortablejs": "^1.15.2",
|
||||
"svelte": "^4.2.18",
|
||||
"tinymce": "^6.8.4",
|
||||
"trix": "^2.1.5",
|
||||
"uuid": "^10.0.0",
|
||||
"vite": "5.2.6"
|
||||
}
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/commands": "^6.6.0",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.2.5",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||
"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",
|
||||
"mustache": "^4.2.0",
|
||||
"postcss": "8.4.31",
|
||||
"sass": "^1.77.8",
|
||||
"sortablejs": "^1.15.2",
|
||||
"svelte": "^4.2.18",
|
||||
"trix": "^2.1.5",
|
||||
"vite": "5.2.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,8 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Lucent\Channel\ChannelService;
|
||||
use Lucent\File\FileService;
|
||||
use Lucent\File\ImageService;
|
||||
use Lucent\Query\Query;
|
||||
use Lucent\Record\InputData\RecordInputData;
|
||||
use Lucent\Record\RecordService;
|
||||
use Lucent\Record\Status;
|
||||
use function Lucent\Response\fail;
|
||||
use function Lucent\Response\ok;
|
||||
|
||||
@@ -27,20 +24,20 @@ class FileController extends Controller
|
||||
public function fromDisk(Request $request, string $disk)
|
||||
{
|
||||
$imagePath = $request->route("any");
|
||||
$disk = $this->fileService->loadDisk($disk);
|
||||
$disk = $this->fileService->loadPublicDisk($disk);
|
||||
return response()->file($disk->path($imagePath));
|
||||
}
|
||||
|
||||
public function thumb(Request $request, string $disk)
|
||||
{
|
||||
$imagePath = "thumbs/" . $request->route("any");
|
||||
$disk = $this->fileService->loadDisk($disk);
|
||||
$disk = $this->fileService->loadPublicDisk($disk);
|
||||
return response()->file($disk->path($imagePath));
|
||||
}
|
||||
|
||||
public function download(Request $request)
|
||||
{
|
||||
$disk = $this->fileService->loadDisk();
|
||||
$disk = $this->fileService->loadPublicDisk();
|
||||
return $disk->download($request->input("path"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user