2019-08-02 15:54:10 +02:00
|
|
|
<script>
|
2020-01-24 12:32:13 +01:00
|
|
|
import ComponentHierarchyChildren from './ComponentHierarchyChildren.svelte';
|
2019-08-02 15:54:10 +02:00
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
import {
|
|
|
|
last,
|
|
|
|
sortBy,
|
|
|
|
filter,
|
2019-08-02 15:54:10 +02:00
|
|
|
map,
|
|
|
|
uniqWith,
|
|
|
|
isEqual,
|
|
|
|
trimCharsStart,
|
|
|
|
trimChars,
|
2019-08-15 09:49:15 +02:00
|
|
|
join,
|
|
|
|
includes
|
2019-08-02 15:54:10 +02:00
|
|
|
} from "lodash/fp";
|
|
|
|
|
|
|
|
import { pipe } from "../common/core";
|
|
|
|
import getIcon from "../common/icon";
|
|
|
|
import { store } from "../builderStore";
|
|
|
|
|
|
|
|
export let components = []
|
|
|
|
export let thisLevel = "";
|
|
|
|
|
2019-08-15 09:49:15 +02:00
|
|
|
let pathPartsThisLevel;
|
|
|
|
let componentsThisLevel;
|
2020-01-24 12:32:13 +01:00
|
|
|
let _components;
|
2019-08-15 09:49:15 +02:00
|
|
|
let subfolders;
|
|
|
|
|
|
|
|
let expandedFolders = [];
|
|
|
|
|
2019-08-02 15:54:10 +02:00
|
|
|
const joinPath = join("/");
|
|
|
|
|
|
|
|
const normalizedName = name => pipe(name, [
|
|
|
|
trimCharsStart("./"),
|
|
|
|
trimCharsStart("~/"),
|
|
|
|
trimCharsStart("../"),
|
|
|
|
trimChars(" ")
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
const isOnThisLevel = (c) =>
|
2019-08-02 15:54:10 +02:00
|
|
|
normalizedName(c.name).split("/").length === pathPartsThisLevel
|
|
|
|
&&
|
|
|
|
(!thisLevel || normalizedName(c.name).startsWith(normalizedName(thisLevel)));
|
|
|
|
|
|
|
|
const notOnThisLevel = (c) => !isOnThisLevel(c);
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
const isInSubfolder = (subfolder, c) =>
|
2019-08-02 15:54:10 +02:00
|
|
|
normalizedName(c.name).startsWith(
|
|
|
|
trimCharsStart("/")(
|
|
|
|
joinPath([thisLevel, subfolder])));
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
const isOnNextLevel = (c) =>
|
2019-08-02 15:54:10 +02:00
|
|
|
normalizedName(c.name).split("/").length === pathPartsThisLevel + 1
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
const lastPartOfName = (c) =>
|
2020-01-24 12:32:13 +01:00
|
|
|
last(c.name ? c.name.split("/") : c._component.split("/"))
|
2019-08-02 15:54:10 +02:00
|
|
|
|
|
|
|
const subFolder = (c) => {
|
|
|
|
const cname = normalizedName(c.name);
|
|
|
|
const folderName = cname.substring(thisLevel.length, cname.length).split("/")[0];
|
|
|
|
|
|
|
|
return ({
|
|
|
|
name: folderName,
|
2019-08-15 09:49:15 +02:00
|
|
|
isExpanded: includes(folderName)(expandedFolders),
|
2019-08-02 15:54:10 +02:00
|
|
|
path: thisLevel + "/" + folderName
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const subComponents = (subfolder) => pipe(components, [
|
|
|
|
filter(c => isInSubfolder(subfolder, c))
|
|
|
|
]);
|
|
|
|
|
|
|
|
const expandFolder = folder => {
|
|
|
|
const expandedFolder = {...folder};
|
2019-08-15 09:49:15 +02:00
|
|
|
if(expandedFolder.isExpanded) {
|
|
|
|
expandedFolder.isExpanded = false;
|
|
|
|
expandedFolders = filter(f => f.name !== folder.name)(expandedFolders);
|
|
|
|
} else {
|
|
|
|
expandedFolder.isExpanded = true;
|
|
|
|
expandedFolders.push(folder.name);
|
|
|
|
}
|
2019-08-02 15:54:10 +02:00
|
|
|
const newFolders = [...subfolders];
|
|
|
|
newFolders.splice(
|
|
|
|
newFolders.indexOf(folder),
|
|
|
|
1,
|
|
|
|
expandedFolder);
|
|
|
|
subfolders = newFolders;
|
2020-01-20 17:47:35 +01:00
|
|
|
|
2019-08-02 15:54:10 +02:00
|
|
|
}
|
|
|
|
|
2019-09-30 05:55:24 +02:00
|
|
|
const isComponentSelected = (type, current,c) =>
|
2020-01-18 00:06:42 +01:00
|
|
|
type==="screen"
|
2020-01-20 17:47:35 +01:00
|
|
|
&& current
|
2019-08-02 15:54:10 +02:00
|
|
|
&& current.name === c.name
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
const isFolderSelected = (current, folder) =>
|
2019-08-02 15:54:10 +02:00
|
|
|
isInSubfolder(current, folder)
|
|
|
|
|
2019-08-15 09:49:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
$: {
|
2020-01-20 17:47:35 +01:00
|
|
|
pathPartsThisLevel = !thisLevel
|
2019-08-15 09:49:15 +02:00
|
|
|
? 1
|
|
|
|
: normalizedName(thisLevel).split("/").length + 1;
|
|
|
|
|
2020-01-24 12:32:13 +01:00
|
|
|
_components =
|
2019-08-15 09:49:15 +02:00
|
|
|
pipe(components, [
|
2020-01-24 12:32:13 +01:00
|
|
|
// filter(isOnThisLevel),
|
|
|
|
map(c => ({component: c, title:lastPartOfName(c)})),
|
2019-08-15 09:49:15 +02:00
|
|
|
sortBy("title")
|
|
|
|
]);
|
|
|
|
|
2020-01-24 12:32:13 +01:00
|
|
|
// subfolders =
|
|
|
|
// pipe(components, [
|
|
|
|
// filter(notOnThisLevel),
|
|
|
|
// sortBy("name"),
|
|
|
|
// map(subFolder),
|
|
|
|
// uniqWith((f1,f2) => f1.path === f2.path)
|
|
|
|
// ]);
|
2019-08-15 09:49:15 +02:00
|
|
|
}
|
|
|
|
|
2019-08-02 15:54:10 +02:00
|
|
|
</script>
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
<div class="root">
|
|
|
|
|
2020-01-24 12:32:13 +01:00
|
|
|
<!-- {#each subfolders as folder}
|
2019-08-02 15:54:10 +02:00
|
|
|
<div class="hierarchy-item folder"
|
|
|
|
on:click|stopPropagation={() => expandFolder(folder)}>
|
|
|
|
<span>{@html getIcon(folder.isExpanded ? "chevron-down" : "chevron-right", "16")}</span>
|
|
|
|
<span class="title" class:currentfolder={$store.currentFrontEndItem && isInSubfolder(folder.name, $store.currentFrontEndItem)}>{folder.name}</span>
|
|
|
|
{#if folder.isExpanded}
|
2020-01-20 17:47:35 +01:00
|
|
|
<svelte:self components={subComponents(folder.name)}
|
2019-08-02 15:54:10 +02:00
|
|
|
thisLevel={folder.path} />
|
|
|
|
{/if}
|
|
|
|
</div>
|
2020-01-24 12:32:13 +01:00
|
|
|
{/each} -->
|
2019-08-02 15:54:10 +02:00
|
|
|
|
2020-01-24 12:32:13 +01:00
|
|
|
{#each _components as component}
|
|
|
|
<div class="hierarchy-item component"
|
|
|
|
class:selected={isComponentSelected($store.currentFrontEndType, $store.currentFrontEndItem, component.component)}
|
2020-01-18 00:06:42 +01:00
|
|
|
on:click|stopPropagation={() => store.setCurrentScreen(component.component.name)}>
|
2020-01-24 12:32:13 +01:00
|
|
|
|
2019-08-02 15:54:10 +02:00
|
|
|
<span class="title">{component.title}</span>
|
|
|
|
</div>
|
2020-01-24 12:32:13 +01:00
|
|
|
{#if component.component.props && component.component.props._children}
|
|
|
|
<ComponentHierarchyChildren components={component.component.props._children} onSelect={store.selectComponent}/>
|
|
|
|
{/if}
|
2019-08-02 15:54:10 +02:00
|
|
|
{/each}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
.root {
|
2020-01-20 17:47:35 +01:00
|
|
|
font-weight: 500;
|
|
|
|
font-size: 0.9rem;
|
|
|
|
color: #828fa5;
|
2019-08-02 15:54:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.hierarchy-item {
|
|
|
|
cursor: pointer;
|
2020-01-20 17:47:35 +01:00
|
|
|
padding: 11px 7px;
|
|
|
|
|
|
|
|
margin: 5px 0;
|
|
|
|
border-radius: 5px;
|
2019-08-02 15:54:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.hierarchy-item:hover {
|
2020-01-20 17:47:35 +01:00
|
|
|
/* color: var(--secondary); */
|
|
|
|
background: #fafafa;
|
2019-08-02 15:54:10 +02:00
|
|
|
}
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
|
2019-08-02 15:54:10 +02:00
|
|
|
|
|
|
|
.currentfolder {
|
|
|
|
color: var(--secondary100);
|
|
|
|
}
|
|
|
|
|
|
|
|
.selected {
|
2020-01-20 17:47:35 +01:00
|
|
|
color: var(--button-text);
|
|
|
|
background: var(--background-button)!important;
|
2019-08-02 15:54:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.title {
|
|
|
|
margin-left: 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-20 17:47:35 +01:00
|
|
|
</style>
|