Conflicted Copy {tag.conflictOf}
diff --git a/app/assets/javascripts/typings/hoist-non-react-statics.d.ts b/app/assets/javascripts/typings/hoist-non-react-statics.d.ts
new file mode 100644
index 00000000000..4a0f7856f2d
--- /dev/null
+++ b/app/assets/javascripts/typings/hoist-non-react-statics.d.ts
@@ -0,0 +1,67 @@
+/* eslint-disable @typescript-eslint/ban-types */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+// Type definitions for hoist-non-react-statics 3.3
+// Project: https://github.com/mridgway/hoist-non-react-statics#readme
+// Definitions by: JounQin
, James Reggio
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.8
+// https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/hoist-non-react-statics
+
+declare module 'hoist-non-react-statics' {
+ interface REACT_STATICS {
+ childContextTypes: true;
+ contextType: true;
+ contextTypes: true;
+ defaultProps: true;
+ displayName: true;
+ getDefaultProps: true;
+ getDerivedStateFromError: true;
+ getDerivedStateFromProps: true;
+ mixins: true;
+ propTypes: true;
+ type: true;
+ }
+
+ interface KNOWN_STATICS {
+ name: true;
+ length: true;
+ prototype: true;
+ caller: true;
+ callee: true;
+ arguments: true;
+ arity: true;
+ }
+
+ interface MEMO_STATICS {
+ $$typeof: true;
+ compare: true;
+ defaultProps: true;
+ displayName: true;
+ propTypes: true;
+ type: true;
+ }
+
+ interface FORWARD_REF_STATICS {
+ $$typeof: true;
+ render: true;
+ defaultProps: true;
+ displayName: true;
+ propTypes: true;
+ }
+
+ export type NonReactStatics<
+ S extends React.ComponentType,
+ C extends {
+ [key: string]: true;
+ } = {}
+ > = {
+ [key in Exclude<
+ keyof S,
+ S extends React.MemoExoticComponent
+ ? keyof MEMO_STATICS | keyof C
+ : S extends React.ForwardRefExoticComponent
+ ? keyof FORWARD_REF_STATICS | keyof C
+ : keyof REACT_STATICS | keyof KNOWN_STATICS | keyof C
+ >]: S[key];
+ };
+}
diff --git a/app/assets/javascripts/ui_models/app_state/tags_state.ts b/app/assets/javascripts/ui_models/app_state/tags_state.ts
index f3fff2b0297..ef63453a6c7 100644
--- a/app/assets/javascripts/ui_models/app_state/tags_state.ts
+++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts
@@ -24,9 +24,10 @@ export class TagsState {
this.tagsCountsState = new TagsCountsState(this.application);
makeObservable(this, {
- tags: observable,
- smartTags: observable,
+ tags: observable.ref,
+ smartTags: observable.ref,
hasFolders: computed,
+ hasAtLeastOneFolder: computed,
assignParent: action,
@@ -76,17 +77,22 @@ export class TagsState {
return this.application.isValidTagParent(parentUuid, tagUuid);
}
- assignParent(tagUuid: string, parentUuid: string | undefined): void {
+ public async assignParent(
+ tagUuid: string,
+ parentUuid: string | undefined
+ ): Promise {
const tag = this.application.findItem(tagUuid) as SNTag;
const parent =
parentUuid && (this.application.findItem(parentUuid) as SNTag);
if (!parent) {
- this.application.unsetTagParent(tag);
+ await this.application.unsetTagParent(tag);
} else {
- this.application.setTagParent(parent, tag);
+ await this.application.setTagParent(parent, tag);
}
+
+ await this.application.sync();
}
get rootTags(): SNTag[] {
@@ -108,6 +114,10 @@ export class TagsState {
public set hasFolders(hasFolders: boolean) {
this.features.hasFolders = hasFolders;
}
+
+ public get hasAtLeastOneFolder(): boolean {
+ return this.tags.some((tag) => !!this.application.getTagParent(tag));
+ }
}
/**
diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss
index 14d9626dfb4..e44610a4462 100644
--- a/app/assets/stylesheets/_tags.scss
+++ b/app/assets/stylesheets/_tags.scss
@@ -53,10 +53,19 @@
.root-drop {
width: '100%';
- padding: 10px;
+ padding: 12px;
opacity: 0;
transition: opacity 0.3s ease-in;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+
+ .sn-icon {
+ margin-right: 0.5rem;
+ }
+
&.active {
opacity: 1;
@@ -68,6 +77,9 @@
}
.tag {
+ font-size: 14px;
+ line-height: 18px;
+
min-height: 30px;
padding: 5px 12px;
cursor: pointer;
@@ -81,11 +93,26 @@
align-items: center;
justify-content: space-between;
- > .tag-icon {
- svg {
- display: block;
- margin: auto;
+ .sn-icon {
+ display: block;
+ margin: 0 auto;
+
+ &.hidden {
+ visibility: hidden;
}
+ }
+
+ > .tag-fold {
+ width: 22px;
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ > .tag-icon {
+ display: flex;
+ align-items: center;
+ height: 100%;
&.draggable {
cursor: move;
@@ -96,13 +123,12 @@
}
}
- > .tag-fold {
- width: 22px;
- }
-
> .title {
@extend .focus\:outline-none;
@extend .focus\:shadow-none;
+ font-size: 14px;
+ line-height: 18px;
+
width: 80%;
background-color: transparent;
font-weight: 600;
@@ -147,7 +173,11 @@
}
.meta {
- padding-left: 20px;
+ padding-left: 3px;
+
+ &.with-folders {
+ padding-left: 25px;
+ }
> .menu {
font-size: 11px;
@@ -179,7 +209,7 @@
&:hover:not(.selected),
&.selected,
&.is-drag-over {
- background-color: var(--sn-stylekit-white);
+ background-color: var(--sn-stylekit-secondary-contrast-background-color);
color: var(--sn-stylekit-secondary-contrast-foreground-color);
> .title {