mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
Updated Classes layout (#4314)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
c75939dcff
commit
bf86948959
@ -80,23 +80,6 @@
|
||||
|
||||
--theme-clockface-sec-arrow: conic-gradient(at 50% -10px, rgba(255, 0, 0, 0), rgba(255, 0, 0, 0) 49%, #F47758 50%, rgba(255, 0, 0, 0) 51%, rgba(255, 0, 0, 0) 100%);
|
||||
--theme-clockface-sec-holder: #F47758;
|
||||
|
||||
// New
|
||||
--global-accent-IconColor: #6796FF;
|
||||
|
||||
--button-accent-LabelColor: #fff;
|
||||
--button-disabled-LabelColor: #8b97ad;
|
||||
--button-accent-IconColor: #fff;
|
||||
--button-disabled-IconColor: #8b97ad;
|
||||
--button-primary-BackgroundColor: #3364e2;
|
||||
--button-primary-BorderColor: #d1d5de1a;
|
||||
--button-primary-hover-BackgroundColor: #6191fe;
|
||||
--button-primary-active-BackgroundColor: #2553cf;
|
||||
--button-primary-loading-LabelColor: #6191fe;
|
||||
--button-negative-loading-LabelColor: #ff9187;
|
||||
--button-negative-BorderColor: #d1d5de26;
|
||||
--button-negative-hover-BackgroundColor: #e34748;
|
||||
--button-negative-active-BackgroundColor: #c42a32;
|
||||
}
|
||||
|
||||
/* Dark Theme */
|
||||
@ -325,48 +308,6 @@
|
||||
--theme-clockface-min-arrow: conic-gradient(at 50% -10px, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0) 49%, #2F2F3A 50%, rgba(0, 0, 0, 0) 51%, rgba(0, 0, 0, 0) 100%);
|
||||
--theme-clockface-arrows-holder: radial-gradient(at top center, #2F2F3A, #555555);
|
||||
--theme-clockface-arrows-shadow: 0 0 1px white;
|
||||
|
||||
// New
|
||||
--global-ui-BackgroundColor: #A5BDFF0D;
|
||||
--global-ui-hover-BackgroundColor: #A5BDFF1A;
|
||||
--global-ui-highlight-BackgroundColor: #A5BDFF0D;
|
||||
--global-ui-hover-highlight-BackgroundColor: #A5BDFF26;
|
||||
--global-surface-01-BackgroundColor: #131925;
|
||||
--global-surface-01-BorderColor: #1F2737;
|
||||
--global-surface-02-BackgroundColor: #19202E;
|
||||
--global-surface-02-BorderColor: #262F40;
|
||||
--global-surface-03-hover-BackgroundColor: #19202E;
|
||||
--global-primary-LinkColor: #4D7FF5;
|
||||
--global-primary-TextColor: #FFFFFF;
|
||||
--global-secondary-TextColor: #C1C9D6;
|
||||
--global-tertiary-TextColor: #8E99AF;
|
||||
--global-accent-TextColor: #4D7FF5;
|
||||
/** Buttons **/
|
||||
--button-subtle-LabelColor: #fff;
|
||||
--button-subtle-IconColor: #fff;
|
||||
--button-disabled-BackgroundColor: #d1d5de0d;
|
||||
--button-primary-loading-LabelColor: #6191fe;
|
||||
--button-secondary-BackgroundColor: #d1d5de0d;
|
||||
--button-secondary-BorderColor: #d1d5de1a;
|
||||
--button-secondary-hover-BackgroundColor: #d1d5de1a;
|
||||
--button-secondary-active-BackgroundColor: #d1d5de26;
|
||||
--button-negative-BackgroundColor: #e34748;
|
||||
--button-tertiary-hover-BackgroundColor: #d1d5de1a;
|
||||
--button-tertiary-active-BackgroundColor: #d1d5de26;
|
||||
--button-menu-active-BorderColor: #d9dee6;
|
||||
/** Editbox **/
|
||||
--input-BackgroundColor: #a5bdff0d;
|
||||
--input-hover-BackgroundColor: #a5bdff1a;
|
||||
--input-BorderColor: #a5bdff0d;
|
||||
--input-TextColor: #ffffff;
|
||||
--input-LabelColor: #ffffff;
|
||||
--input-filled-LabelColor: #8b97ad;
|
||||
--input-PlaceholderColor: #8b97ad;
|
||||
--input-hover-PlaceholderColor: #ffffff;
|
||||
--input-focus-PlaceholderColor: #556178;
|
||||
--input-HelperColor: #8b97ad;
|
||||
--input-error-BorderColor: #fb6863;
|
||||
--input-search-IconColor: #ffffff;
|
||||
}
|
||||
|
||||
/* Light Theme */
|
||||
@ -595,46 +536,4 @@
|
||||
--theme-clockface-min-arrow: conic-gradient(at 50% -10px, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 49%, white 50%, rgba(255, 255, 255, 0) 51%, rgba(255, 255, 255, 0) 100%);
|
||||
--theme-clockface-arrows-holder: radial-gradient(at top center, #eee, #aaa);
|
||||
--theme-clockface-arrows-shadow: 0 0 1px black;
|
||||
|
||||
// New
|
||||
--global-ui-BackgroundColor: #1530720D;
|
||||
--global-ui-hover-BackgroundColor: #1530721A;
|
||||
--global-ui-highlight-BackgroundColor: #A5BDFF26;
|
||||
--global-ui-hover-highlight-BackgroundColor: #A5BDFF40;
|
||||
--global-surface-01-BackgroundColor: #F8F9FA;
|
||||
--global-surface-01-BorderColor: #DDE1E9;
|
||||
--global-surface-02-BackgroundColor: #19202E;
|
||||
--global-surface-02-BorderColor: #EBEEF2;
|
||||
--global-surface-03-hover-BackgroundColor: #F8F9FA;
|
||||
--global-primary-LinkColor: #3566E2;
|
||||
--global-primary-TextColor: #0F121A;
|
||||
--global-secondary-TextColor: #5A667E;
|
||||
--global-tertiary-TextColor: #7B879E;
|
||||
--global-accent-TextColor: #3566E2;
|
||||
/** Buttons **/
|
||||
--button-subtle-LabelColor: #000;
|
||||
--button-subtle-IconColor: #000;
|
||||
--button-disabled-BackgroundColor: #1725470d;
|
||||
--button-primary-loading-LabelColor: #95baff;
|
||||
--button-secondary-BackgroundColor: #1725470d;
|
||||
--button-secondary-BorderColor: #1725471a;
|
||||
--button-secondary-hover-BackgroundColor: #1725471a;
|
||||
--button-secondary-active-BackgroundColor: #17254726;
|
||||
--button-negative-BackgroundColor: #ea4c4c;
|
||||
--button-tertiary-hover-BackgroundColor: #1725471a;
|
||||
--button-tertiary-active-BackgroundColor: #17254726;
|
||||
--button-menu-active-BorderColor: #0f121a;
|
||||
/** Editbox **/
|
||||
--input-BackgroundColor: #1530720d;
|
||||
--input-hover-BackgroundColor: #1530721a;
|
||||
--input-BorderColor: #1530720d;
|
||||
--input-TextColor: #0f121a;
|
||||
--input-LabelColor: #0f121a;
|
||||
--input-filled-LabelColor: #556178;
|
||||
--input-PlaceholderColor: #556178;
|
||||
--input-hover-PlaceholderColor: #0f121a;
|
||||
--input-focus-PlaceholderColor: #8b97ad;
|
||||
--input-HelperColor: #556178;
|
||||
--input-error-BorderColor: #e34748;
|
||||
--input-search-IconColor: #0f121a;
|
||||
}
|
||||
|
137
packages/theme/styles/_lumia-colors.scss
Normal file
137
packages/theme/styles/_lumia-colors.scss
Normal file
@ -0,0 +1,137 @@
|
||||
//
|
||||
// Copyright © 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
/* Common Colors */
|
||||
* {
|
||||
--global-accent-IconColor: #6796FF;
|
||||
--global-on-accent-TextColor: #FFFFFF;
|
||||
--global-focus-inset-BorderColor: #0D121C;
|
||||
|
||||
--button-accent-LabelColor: #fff;
|
||||
--button-disabled-LabelColor: #8b97ad;
|
||||
--button-accent-IconColor: #fff;
|
||||
--button-disabled-IconColor: #8b97ad;
|
||||
--button-primary-BackgroundColor: #3364e2;
|
||||
--button-primary-BorderColor: #d1d5de1a;
|
||||
--button-primary-hover-BackgroundColor: #6191fe;
|
||||
--button-primary-active-BackgroundColor: #2553cf;
|
||||
--button-primary-loading-LabelColor: #6191fe;
|
||||
--button-negative-loading-LabelColor: #ff9187;
|
||||
--button-negative-BorderColor: #d1d5de26;
|
||||
--button-negative-hover-BackgroundColor: #e34748;
|
||||
--button-negative-active-BackgroundColor: #c42a32;
|
||||
}
|
||||
|
||||
/* Dark Theme */
|
||||
.theme-dark {
|
||||
--global-ui-BackgroundColor: #A5BDFF0D;
|
||||
--global-ui-hover-BackgroundColor: #A5BDFF1A;
|
||||
--global-ui-highlight-BackgroundColor: #A5BDFF0D;
|
||||
--global-ui-hover-highlight-BackgroundColor: #A5BDFF26;
|
||||
--global-surface-01-BackgroundColor: #131925;
|
||||
--global-surface-01-BorderColor: #1F2737;
|
||||
--global-surface-02-BackgroundColor: #19202E;
|
||||
--global-surface-02-BorderColor: #262F40;
|
||||
--global-surface-03-hover-BackgroundColor: #19202E;
|
||||
--global-subtle-ui-BorderColor: #A5BDFF0D;
|
||||
--global-popover-BackgroundColor: #262F40;
|
||||
--global-popover-hover-BackgroundColor: #1F2737;
|
||||
--global-popover-BorderColor: #A5BDFF1A;
|
||||
--global-primary-LinkColor: #4D7FF5;
|
||||
--global-primary-TextColor: #FFFFFF;
|
||||
--global-secondary-TextColor: #C1C9D6;
|
||||
--global-tertiary-TextColor: #8E99AF;
|
||||
--global-accent-TextColor: #4D7FF5;
|
||||
--global-focus-BorderColor: #2A59D6;
|
||||
|
||||
/** Buttons **/
|
||||
--button-subtle-LabelColor: #fff;
|
||||
--button-subtle-IconColor: #fff;
|
||||
--button-disabled-BackgroundColor: #d1d5de0d;
|
||||
--button-primary-loading-LabelColor: #6191fe;
|
||||
--button-secondary-BackgroundColor: #d1d5de0d;
|
||||
--button-secondary-BorderColor: #d1d5de1a;
|
||||
--button-secondary-hover-BackgroundColor: #d1d5de1a;
|
||||
--button-secondary-active-BackgroundColor: #d1d5de26;
|
||||
--button-negative-BackgroundColor: #e34748;
|
||||
--button-tertiary-hover-BackgroundColor: #d1d5de1a;
|
||||
--button-tertiary-active-BackgroundColor: #d1d5de26;
|
||||
--button-menu-active-BorderColor: #d9dee6;
|
||||
|
||||
/** Editbox **/
|
||||
--input-BackgroundColor: #a5bdff0d;
|
||||
--input-hover-BackgroundColor: #a5bdff1a;
|
||||
--input-BorderColor: #a5bdff0d;
|
||||
--input-TextColor: #ffffff;
|
||||
--input-LabelColor: #ffffff;
|
||||
--input-filled-LabelColor: #8b97ad;
|
||||
--input-PlaceholderColor: #8b97ad;
|
||||
--input-hover-PlaceholderColor: #ffffff;
|
||||
--input-focus-PlaceholderColor: #556178;
|
||||
--input-HelperColor: #8b97ad;
|
||||
--input-error-BorderColor: #fb6863;
|
||||
--input-search-IconColor: #ffffff;
|
||||
}
|
||||
|
||||
/* Light Theme */
|
||||
.theme-light {
|
||||
--global-ui-BackgroundColor: #1530720D;
|
||||
--global-ui-hover-BackgroundColor: #1530721A;
|
||||
--global-ui-highlight-BackgroundColor: #A5BDFF26;
|
||||
--global-ui-hover-highlight-BackgroundColor: #A5BDFF40;
|
||||
--global-surface-01-BackgroundColor: #F8F9FA;
|
||||
--global-surface-01-BorderColor: #DDE1E9;
|
||||
--global-surface-02-BackgroundColor: #19202E;
|
||||
--global-surface-02-BorderColor: #EBEEF2;
|
||||
--global-surface-03-hover-BackgroundColor: #F8F9FA;
|
||||
--global-subtle-ui-BorderColor: #1530720D;
|
||||
--global-popover-BackgroundColor: #131925;
|
||||
--global-popover-hover-BackgroundColor: #1F2737;
|
||||
--global-popover-BorderColor: #A5BDFF26;
|
||||
--global-primary-LinkColor: #3566E2;
|
||||
--global-primary-TextColor: #0F121A;
|
||||
--global-secondary-TextColor: #5A667E;
|
||||
--global-tertiary-TextColor: #7B879E;
|
||||
--global-accent-TextColor: #3566E2;
|
||||
--global-focus-BorderColor: #204DC8;
|
||||
|
||||
/** Buttons **/
|
||||
--button-subtle-LabelColor: #000;
|
||||
--button-subtle-IconColor: #000;
|
||||
--button-disabled-BackgroundColor: #1725470d;
|
||||
--button-primary-loading-LabelColor: #95baff;
|
||||
--button-secondary-BackgroundColor: #1725470d;
|
||||
--button-secondary-BorderColor: #1725471a;
|
||||
--button-secondary-hover-BackgroundColor: #1725471a;
|
||||
--button-secondary-active-BackgroundColor: #17254726;
|
||||
--button-negative-BackgroundColor: #ea4c4c;
|
||||
--button-tertiary-hover-BackgroundColor: #1725471a;
|
||||
--button-tertiary-active-BackgroundColor: #17254726;
|
||||
--button-menu-active-BorderColor: #0f121a;
|
||||
|
||||
/** Editbox **/
|
||||
--input-BackgroundColor: #1530720d;
|
||||
--input-hover-BackgroundColor: #1530721a;
|
||||
--input-BorderColor: #1530720d;
|
||||
--input-TextColor: #0f121a;
|
||||
--input-LabelColor: #0f121a;
|
||||
--input-filled-LabelColor: #556178;
|
||||
--input-PlaceholderColor: #556178;
|
||||
--input-hover-PlaceholderColor: #0f121a;
|
||||
--input-focus-PlaceholderColor: #8b97ad;
|
||||
--input-HelperColor: #556178;
|
||||
--input-error-BorderColor: #e34748;
|
||||
--input-search-IconColor: #0f121a;
|
||||
}
|
@ -81,6 +81,166 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.hulyHeader-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--spacing-1_5) var(--spacing-2);
|
||||
width: 100%;
|
||||
height: var(--spacing-6_5);
|
||||
border-bottom: 1px solid var(--theme-divider-color); // var(--global-surface-02-BorderColor);
|
||||
|
||||
.hulyHeader-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
color: var(--button-disabled-IconColor);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--button-subtle-LabelColor);
|
||||
}
|
||||
}
|
||||
.hulyHeader-divider {
|
||||
flex-shrink: 0;
|
||||
margin: 0 var(--spacing-2);
|
||||
width: 1px;
|
||||
height: var(--spacing-4);
|
||||
background-color: var(--theme-divider-color); // var(--global-surface-02-BorderColor);
|
||||
}
|
||||
.hulyHeader-titleGroup,
|
||||
.hulyHeader-buttonsGroup {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
.hulyHeader-titleGroup {
|
||||
flex-grow: 1;
|
||||
gap: var(--spacing-0_5);
|
||||
}
|
||||
.hulyHeader-buttonsGroup {
|
||||
gap: var(--spacing-1);
|
||||
margin-left: var(--spacing-2);
|
||||
}
|
||||
.hulyHotKey-item {
|
||||
margin-right: .625rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.hulyModal-container,
|
||||
.hulyModal-container .hulyModal-content,
|
||||
.hulyModal-container .hulyModal-content__titleGroup,
|
||||
.hulyModal-container .hulyModal-content__settingsSet,
|
||||
.hulyModal-container .hulyModal-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
.hulyModal-container {
|
||||
height: 100%;
|
||||
border-top: 1px solid transparent;
|
||||
|
||||
.hulyModal-content {
|
||||
padding: var(--spacing-2) var(--spacing-1_5) var(--spacing-6);
|
||||
height: 100%;
|
||||
|
||||
&__titleGroup {
|
||||
flex-shrink: 0;
|
||||
padding: var(--spacing-2) var(--spacing-0_5) 0;
|
||||
|
||||
.hulyChip-item {
|
||||
margin: 0 0 var(--spacing-0_75) var(--spacing-1_5);
|
||||
}
|
||||
}
|
||||
&__settingsSet {
|
||||
flex-shrink: 0;
|
||||
padding: var(--spacing-4) var(--spacing-2_5) 0;
|
||||
|
||||
&-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: var(--spacing-1_5) 0;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
min-height: var(--global-max-Size);
|
||||
border-bottom: 1px solid var(--global-subtle-ui-BorderColor);
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid var(--global-subtle-ui-BorderColor);
|
||||
}
|
||||
.label {
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
font-size: .75rem;
|
||||
font-style: normal;
|
||||
line-height: 1rem;
|
||||
color: var(--global-secondary-TextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.hulyModal-footer {
|
||||
flex-direction: row-reverse;
|
||||
flex-shrink: 0;
|
||||
gap: var(--spacing-1);
|
||||
padding: var(--spacing-2) var(--spacing-2_5);
|
||||
border-top: 1px solid var(--theme-divider-color); // var(--global-surface-01-BorderColor);
|
||||
}
|
||||
|
||||
&.type-aside .hulyHeader-container {
|
||||
border-radius: 0 var(--small-focus-BorderRadius) 0 0;
|
||||
|
||||
.hulyHeader-titleGroup {
|
||||
text-transform: uppercase;
|
||||
font-family: var(--font-family);
|
||||
font-weight: 500;
|
||||
font-size: .75rem;
|
||||
font-style: normal;
|
||||
line-height: 1rem;
|
||||
color: var(--global-secondary-TextColor);
|
||||
}
|
||||
.hulyHeader-buttonsGroup {
|
||||
gap: var(--spacing-0_5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hulyChip-item {
|
||||
padding: var(--spacing-0_25) var(--spacing-0_5);
|
||||
width: fit-content;
|
||||
text-transform: uppercase;
|
||||
color: var(--global-tertiary-TextColor);
|
||||
background-color: var(--global-ui-BackgroundColor);
|
||||
border-radius: var(--extra-small-BorderRadius);
|
||||
}
|
||||
|
||||
.hulyHotKey-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: var(--spacing-0_25) var(--spacing-0_5);
|
||||
height: var(--global-min-Size);
|
||||
min-width: var(--global-min-Size);
|
||||
text-align: center;
|
||||
font-family: var(--font-family);
|
||||
font-weight: 400;
|
||||
font-size: .625rem;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
color: var(--global-primary-TextColor);
|
||||
background: var(--button-secondary-hover-BackgroundColor);
|
||||
border-radius: var(--extra-small-BorderRadius);
|
||||
}
|
||||
|
||||
/* Component */
|
||||
.antiComponent {
|
||||
display: flex;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
@import "./_vars.scss";
|
||||
@import "./_colors.scss";
|
||||
@import "./_lumia-colors.scss";
|
||||
@import "./_layouts.scss";
|
||||
@import "./common.scss";
|
||||
@import "./button.scss";
|
||||
|
@ -14,22 +14,25 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { IconMaximize, IconMinimize } from '..'
|
||||
import { IconMaximize, IconMinimize, IconClose, ButtonIcon } from '..'
|
||||
|
||||
export let type: 'type-aside' | 'type-component' = 'type-component'
|
||||
export let minimize: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<div class="hulyHeader-container">
|
||||
<button class="hulyHeader-button" on:click={() => dispatch('resize', minimize)}>
|
||||
{#if minimize}
|
||||
<IconMinimize size={'small'} />
|
||||
{:else}
|
||||
<IconMaximize size={'small'} />
|
||||
{/if}
|
||||
</button>
|
||||
<div class="hulyHeader-divider" />
|
||||
{#if type === 'type-component'}
|
||||
<button class="hulyHeader-button" on:click={() => dispatch('resize', minimize)}>
|
||||
{#if minimize}
|
||||
<IconMinimize size={'small'} />
|
||||
{:else}
|
||||
<IconMaximize size={'small'} />
|
||||
{/if}
|
||||
</button>
|
||||
<div class="hulyHeader-divider" />
|
||||
{/if}
|
||||
<div class="hulyHeader-titleGroup">
|
||||
<slot />
|
||||
</div>
|
||||
@ -38,52 +41,9 @@
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
{/if}
|
||||
{#if type === 'type-aside'}
|
||||
<div class="hulyHeader-divider" />
|
||||
<div class="hulyHotKey-item">Esc</div>
|
||||
<ButtonIcon icon={IconClose} kind={'tertiary'} size={'small'} on:click={() => dispatch('close')} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.hulyHeader-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--spacing-1_5) var(--spacing-2);
|
||||
width: 100%;
|
||||
height: var(--spacing-6_5);
|
||||
border-bottom: 1px solid var(--theme-divider-color); // var(--global-surface-02-BorderColor);
|
||||
|
||||
.hulyHeader-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
color: var(--button-disabled-IconColor);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--button-subtle-LabelColor);
|
||||
}
|
||||
}
|
||||
.hulyHeader-divider {
|
||||
flex-shrink: 0;
|
||||
margin: 0 var(--spacing-2);
|
||||
width: 1px;
|
||||
height: var(--spacing-4);
|
||||
background-color: var(--theme-divider-color); // var(--global-surface-02-BorderColor);
|
||||
}
|
||||
.hulyHeader-titleGroup,
|
||||
.hulyHeader-buttonsGroup {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
.hulyHeader-titleGroup {
|
||||
flex-grow: 1;
|
||||
gap: var(--spacing-0_5);
|
||||
}
|
||||
.hulyHeader-buttonsGroup {
|
||||
gap: var(--spacing-1);
|
||||
margin-left: var(--spacing-2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
74
packages/ui/src/components/Modal.svelte
Normal file
74
packages/ui/src/components/Modal.svelte
Normal file
@ -0,0 +1,74 @@
|
||||
<!--
|
||||
// Copyright © 2023 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import Header from './Header.svelte'
|
||||
import Label from './Label.svelte'
|
||||
import ButtonIcon from './ButtonIcon.svelte'
|
||||
import ButtonBase from './ButtonBase.svelte'
|
||||
import Scroller from './Scroller.svelte'
|
||||
import IconDelete from './icons/Delete.svelte'
|
||||
import IconCopy from './icons/Copy.svelte'
|
||||
import ui from '..'
|
||||
|
||||
export let type: 'type-aside' | 'type-component'
|
||||
export let label: IntlString
|
||||
export let labelProps: any | undefined = undefined
|
||||
export let okAction: () => Promise<void> | void
|
||||
export let onCancel: (() => void) | undefined = undefined
|
||||
export let canSave: boolean = false
|
||||
export let okLabel: IntlString = ui.string.Ok
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function close (): void {
|
||||
if (onCancel) onCancel()
|
||||
else dispatch('close')
|
||||
}
|
||||
function onKeyDown (ev: KeyboardEvent) {
|
||||
if (ev.key === 'Escape') close()
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
|
||||
<div class="hulyModal-container {type}">
|
||||
<Header {type} on:close={close}>
|
||||
<Label {label} params={labelProps} />
|
||||
<svelte:fragment slot="actions">
|
||||
<ButtonIcon icon={IconDelete} size={'small'} kind={'tertiary'} />
|
||||
<ButtonIcon icon={IconCopy} size={'small'} kind={'tertiary'} />
|
||||
</svelte:fragment>
|
||||
</Header>
|
||||
<div class="hulyModal-content">
|
||||
<Scroller>
|
||||
<slot />
|
||||
</Scroller>
|
||||
</div>
|
||||
{#if type === 'type-aside'}
|
||||
<div class="hulyModal-footer">
|
||||
<ButtonBase
|
||||
type={'type-button'}
|
||||
kind={'primary'}
|
||||
size={'large'}
|
||||
label={okLabel}
|
||||
on:click={okAction}
|
||||
disabled={!canSave}
|
||||
/>
|
||||
<ButtonBase type={'type-button'} kind={'secondary'} size={'large'} label={ui.string.Cancel} on:click={onCancel} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
export let label: string
|
||||
import { IntlString, translate } from '@hcengineering/platform'
|
||||
import Label from './Label.svelte'
|
||||
import { themeStore } from '..'
|
||||
|
||||
export let label: IntlString
|
||||
export let value: string | undefined = undefined
|
||||
export let kind: 'default' | 'ghost' = 'default'
|
||||
export let size: 'small' | 'large' = 'small'
|
||||
@ -22,9 +26,14 @@
|
||||
export let password: boolean = false
|
||||
export let limit: number = 0
|
||||
|
||||
$: labeled = kind === 'default' && size === 'large'
|
||||
$: placeholder = labeled ? ' ' : label
|
||||
$: maxlength = limit === 0 ? null : limit
|
||||
|
||||
let placeholderStr: string = ''
|
||||
$: ph = translate(label, {}, $themeStore.language).then((r) => {
|
||||
placeholderStr = r
|
||||
})
|
||||
$: labeled = kind === 'default' && size === 'large'
|
||||
$: placeholder = labeled ? ' ' : placeholderStr
|
||||
</script>
|
||||
|
||||
<label class="editbox-wrapper {kind} {size}" class:error class:disabled>
|
||||
@ -61,7 +70,7 @@
|
||||
on:input
|
||||
/>
|
||||
{/if}
|
||||
{#if labeled}<div class="font-regular-14 label">{label}</div>{/if}
|
||||
{#if labeled}<div class="font-regular-14 label"><Label {label} /></div>{/if}
|
||||
</label>
|
||||
|
||||
<style lang="scss">
|
||||
|
170
packages/ui/src/components/SearchInput.svelte
Normal file
170
packages/ui/src/components/SearchInput.svelte
Normal file
@ -0,0 +1,170 @@
|
||||
<!--
|
||||
// Copyright © 2023 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import IconSearch from './icons/Search.svelte'
|
||||
import IconClose from './icons/Close.svelte'
|
||||
|
||||
export let value: string | undefined = undefined
|
||||
export let placeholder: string
|
||||
export let collapsed: boolean = false
|
||||
|
||||
let input: HTMLInputElement
|
||||
</script>
|
||||
|
||||
<label class="searchInput-wrapper" class:collapsed class:filled={value && value !== ''}>
|
||||
<div class="searchInput-icon">
|
||||
<div><IconSearch size={'small'} /></div>
|
||||
</div>
|
||||
<input
|
||||
bind:this={input}
|
||||
type="text"
|
||||
class="font-regular-14"
|
||||
bind:value
|
||||
{placeholder}
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
on:change
|
||||
on:input
|
||||
/>
|
||||
<button
|
||||
class="searchInput-button"
|
||||
on:click={() => {
|
||||
value = ''
|
||||
input.focus()
|
||||
}}
|
||||
>
|
||||
<div><IconClose size={'small'} /></div>
|
||||
</button>
|
||||
</label>
|
||||
|
||||
<style lang="scss">
|
||||
.searchInput-wrapper {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
padding: 0 var(--spacing-0_5) 0 0;
|
||||
height: var(--spacing-4);
|
||||
min-width: var(--spacing-4);
|
||||
background-color: var(--input-BackgroundColor);
|
||||
border-radius: var(--small-BorderRadius);
|
||||
box-shadow: inset 0 0 0 1px var(--input-BorderColor);
|
||||
transition: max-width 0.2s;
|
||||
cursor: text;
|
||||
|
||||
.searchInput-icon,
|
||||
.searchInput-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
|
||||
div {
|
||||
width: var(--spacing-2);
|
||||
height: var(--spacing-2);
|
||||
}
|
||||
}
|
||||
.searchInput-icon {
|
||||
margin: 0 var(--spacing-0_5) 0 0;
|
||||
width: var(--spacing-4);
|
||||
height: var(--spacing-4);
|
||||
fill: var(--input-search-IconColor);
|
||||
border-radius: var(--small-BorderRadius);
|
||||
outline: none;
|
||||
cursor: text;
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.searchInput-button {
|
||||
visibility: hidden;
|
||||
width: var(--spacing-3);
|
||||
height: var(--spacing-3);
|
||||
fill: var(--global-primary-TextColor);
|
||||
border-radius: var(--extra-small-BorderRadius);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--button-tertiary-hover-BackgroundColor);
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--button-tertiary-active-BackgroundColor);
|
||||
border-color: var(--button-menu-active-BorderColor);
|
||||
}
|
||||
&:focus {
|
||||
outline: 2px solid var(--global-focus-BorderColor);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 0;
|
||||
margin-right: var(--spacing-1_5);
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--input-TextColor);
|
||||
caret-color: var(--global-focus-BorderColor);
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
appearance: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--input-PlaceholderColor);
|
||||
}
|
||||
&:not(:placeholder-shown) + .searchInput-button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--input-hover-BackgroundColor);
|
||||
|
||||
input::placeholder {
|
||||
color: var(--input-hover-PlaceholderColor);
|
||||
}
|
||||
}
|
||||
&:active,
|
||||
&:focus-within {
|
||||
padding: 0 var(--spacing-0_5) 0 0;
|
||||
max-width: 100%;
|
||||
background-color: var(--input-BackgroundColor);
|
||||
outline: 2px solid var(--global-focus-BorderColor);
|
||||
outline-offset: 2px;
|
||||
|
||||
input::placeholder {
|
||||
color: var(--input-focus-PlaceholderColor);
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsed:not(:focus-within, :active, .filled) {
|
||||
padding: 0;
|
||||
max-width: var(--spacing-4);
|
||||
|
||||
.searchInput-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
input:not(:placeholder-shown) + .searchInput-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -3,8 +3,8 @@
|
||||
export let fill: string = 'currentColor'
|
||||
</script>
|
||||
|
||||
<svg class="svg-{size}" {fill} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6.29289 6.29338C5.90237 6.68391 5.90237 7.31707 6.29289 7.70759L14.5858 16.0005L6.29289 24.2934C5.90237 24.6839 5.90237 25.3171 6.29289 25.7076C6.68342 26.0981 7.31658 26.0981 7.70711 25.7076L16 17.4147L24.2929 25.7076C24.6834 26.0981 25.3166 26.0981 25.7071 25.7076C26.0976 25.3171 26.0976 24.6839 25.7071 24.2934L17.4142 16.0005L25.7071 7.70759C26.0976 7.31707 26.0976 6.68391 25.7071 6.29338C25.3166 5.90286 24.6834 5.90286 24.2929 6.29338L16 14.5863L7.70711 6.29338C7.31658 5.90286 6.68342 5.90286 6.29289 6.29338Z"
|
||||
d="M3.14645 3.14645C2.95118 3.34171 2.95118 3.65829 3.14645 3.85355L7.29289 8L3.14645 12.1464C2.95118 12.3417 2.95118 12.6583 3.14645 12.8536C3.34171 13.0488 3.65829 13.0488 3.85355 12.8536L8 8.70711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.70711 8L12.8536 3.85355C13.0488 3.65829 13.0488 3.34171 12.8536 3.14645C12.6583 2.95118 12.3417 2.95118 12.1464 3.14645L8 7.29289L3.85355 3.14645C3.65829 2.95118 3.34171 2.95118 3.14645 3.14645Z"
|
||||
/>
|
||||
</svg>
|
||||
|
@ -131,6 +131,7 @@ export { default as ButtonIcon } from './components/ButtonIcon.svelte'
|
||||
export { default as ModernEditbox } from './components/ModernEditbox.svelte'
|
||||
export { default as NavItem } from './components/NavItem.svelte'
|
||||
export { default as NavGroup } from './components/NavGroup.svelte'
|
||||
export { default as Modal } from './components/Modal.svelte'
|
||||
|
||||
export { default as IconAdd } from './components/icons/Add.svelte'
|
||||
export { default as IconCircleAdd } from './components/icons/CircleAdd.svelte'
|
||||
|
@ -160,7 +160,8 @@ export const workbenchSeparators: DefSeparators = [
|
||||
|
||||
export const settingsSeparators: DefSeparators = [
|
||||
{ minSize: 12.5, size: 17.5, maxSize: 22.5, float: 'navigator' },
|
||||
null
|
||||
null,
|
||||
{ minSize: 17, size: 30, maxSize: 32, float: 'aside' }
|
||||
]
|
||||
|
||||
export const separatorsStore = writable<string[]>([])
|
||||
|
@ -42,13 +42,16 @@
|
||||
Menu,
|
||||
getEventPositionElement,
|
||||
showPopup,
|
||||
IconSettings
|
||||
IconSettings,
|
||||
IconOpenedArrow
|
||||
} from '@hcengineering/ui'
|
||||
import { getContextActions } from '@hcengineering/view-resources'
|
||||
import settings from '../plugin'
|
||||
import CreateAttribute from './CreateAttribute.svelte'
|
||||
import EditAttribute from './EditAttribute.svelte'
|
||||
import EditClassLabel from './EditClassLabel.svelte'
|
||||
import { settingsStore, clearSettingsStore } from '../store'
|
||||
import TypesPopup from './typeEditors/TypesPopup.svelte'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let ofClass: Ref<Class<Doc>> | undefined = undefined
|
||||
@ -70,6 +73,8 @@
|
||||
|
||||
let clazz: Class<Doc> | undefined
|
||||
let hovered: number | null = null
|
||||
let selected: number | null = null
|
||||
let btnAdd: ButtonIcon
|
||||
|
||||
$: classQuery.query(core.class.Class, { _id: _class }, (res) => {
|
||||
clazz = res.shift()
|
||||
@ -96,8 +101,11 @@
|
||||
attributes = getCustomAttributes(_class)
|
||||
}
|
||||
|
||||
export function createAttribute (): void {
|
||||
showPopup(CreateAttribute, { _class }, 'top', update)
|
||||
export function createAttribute (ev: MouseEvent): void {
|
||||
showPopup(TypesPopup, { _class }, getEventPositionElement(ev), (_id) => {
|
||||
if (_id !== undefined) $settingsStore = { component: CreateAttribute, props: { _id, _class } }
|
||||
})
|
||||
// showPopup(CreateAttribute, { _class }, 'top', update)
|
||||
}
|
||||
|
||||
export async function editAttribute (attribute: AnyAttribute, exist: boolean): Promise<void> {
|
||||
@ -130,7 +138,7 @@
|
||||
label: presentation.string.Edit,
|
||||
icon: IconEdit,
|
||||
action: async () => {
|
||||
await editAttribute(attribute, exist)
|
||||
await selectAttribute(attribute, row)
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -180,6 +188,23 @@
|
||||
function editLabel (evt: MouseEvent): void {
|
||||
showPopup(EditClassLabel, { clazz }, getEventPositionElement(evt))
|
||||
}
|
||||
async function selectAttribute (attribute: AnyAttribute, n: number): Promise<void> {
|
||||
if (selected === n) {
|
||||
selected = null
|
||||
clearSettingsStore()
|
||||
return
|
||||
}
|
||||
selected = n
|
||||
const exist = (await client.findOne(attribute.attributeOf, { [attribute.name]: { $exists: true } })) !== undefined
|
||||
$settingsStore = { component: EditAttribute, props: { attribute, exist } }
|
||||
}
|
||||
settingsStore.subscribe((value) => {
|
||||
if (value.component == null) selected = null
|
||||
})
|
||||
const classUpdated = (_clazz: Ref<Class<Doc>>): void => {
|
||||
selected = null
|
||||
}
|
||||
$: classUpdated(_class)
|
||||
</script>
|
||||
|
||||
{#if showTitle}
|
||||
@ -200,28 +225,41 @@
|
||||
<div class="hulyTableAttr-header font-medium-12">
|
||||
<IconSettings size={'small'} />
|
||||
<span><Label label={settings.string.ClassProperties} /></span>
|
||||
<ButtonIcon kind={'primary'} icon={IconAdd} size={'small'} on:click={createAttribute} />
|
||||
<ButtonIcon
|
||||
bind:this={btnAdd}
|
||||
kind={'primary'}
|
||||
icon={IconAdd}
|
||||
size={'small'}
|
||||
on:click={(ev) => {
|
||||
createAttribute(ev)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{#if attributes.length}
|
||||
<div class="hulyTableAttr-content">
|
||||
{#each attributes as attr, i}
|
||||
{@const attrType = getAttrType(attr.type)}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="hulyTableAttr-content__row"
|
||||
class:hovered={hovered === i}
|
||||
class:selected={selected === i}
|
||||
on:contextmenu={(ev) => {
|
||||
ev.preventDefault()
|
||||
void showMenu(ev, attr, i)
|
||||
}}
|
||||
on:click={async () => {
|
||||
void selectAttribute(attr, i)
|
||||
}}
|
||||
>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="hulyTableAttr-content__row-dragMenu" on:click={(ev) => showMenu(ev, attr, i)}>
|
||||
<div class="hulyTableAttr-content__row-dragMenu" on:click|stopPropagation={(ev) => showMenu(ev, attr, i)}>
|
||||
<IconMoreV2 size={'small'} />
|
||||
</div>
|
||||
{#if attr.isCustom}
|
||||
<div class="hulyTableAttr-content__row-chip font-medium-12">
|
||||
<div class="hulyChip-item font-medium-12">
|
||||
<Label label={settings.string.Custom} />
|
||||
</div>
|
||||
{/if}
|
||||
@ -249,6 +287,9 @@
|
||||
{/await}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="hulyTableAttr-content__row-arrow">
|
||||
<IconOpenedArrow size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@ -307,11 +348,6 @@
|
||||
border-radius: var(--small-BorderRadius);
|
||||
cursor: pointer;
|
||||
|
||||
&.hovered,
|
||||
&:hover {
|
||||
background-color: var(--theme-table-header-color); // var(--global-surface-03-hover-BackgroundColor);
|
||||
}
|
||||
|
||||
&-dragMenu {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -321,13 +357,6 @@
|
||||
height: var(--global-extra-small-Size);
|
||||
border-radius: var(--extra-small-BorderRadius);
|
||||
}
|
||||
&-chip {
|
||||
padding: var(--spacing-0_25) var(--spacing-0_5);
|
||||
text-transform: uppercase;
|
||||
color: var(--global-tertiary-TextColor);
|
||||
background-color: var(--global-ui-BackgroundColor);
|
||||
border-radius: var(--extra-small-BorderRadius);
|
||||
}
|
||||
&-icon {
|
||||
width: var(--global-min-Size);
|
||||
height: var(--global-min-Size);
|
||||
@ -352,6 +381,38 @@
|
||||
text-transform: uppercase;
|
||||
color: var(--global-secondary-TextColor);
|
||||
}
|
||||
&-arrow {
|
||||
display: none;
|
||||
flex-shrink: 0;
|
||||
width: var(--global-min-Size);
|
||||
height: var(--global-min-Size);
|
||||
color: var(--global-primary-LinkColor);
|
||||
}
|
||||
|
||||
&.hovered,
|
||||
&:hover {
|
||||
background-color: var(--theme-table-header-color); // var(--global-surface-03-hover-BackgroundColor);
|
||||
}
|
||||
&.selected {
|
||||
background-color: var(--theme-table-header-color); // var(--global-surface-03-hover-BackgroundColor);
|
||||
|
||||
.hulyTableAttr-content__row-icon,
|
||||
.hulyTableAttr-content__row-arrow,
|
||||
.hulyTableAttr-content__row-label {
|
||||
color: var(--global-primary-LinkColor);
|
||||
}
|
||||
.hulyTableAttr-content__row-type {
|
||||
color: var(--global-primary-TextColor);
|
||||
}
|
||||
.hulyTableAttr-content__row-label {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
&.hovered .hulyTableAttr-content__row-arrow,
|
||||
&:hover .hulyTableAttr-content__row-arrow,
|
||||
&.selected .hulyTableAttr-content__row-arrow {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
import { filterDescendants } from '../utils'
|
||||
import ClassAttributes from './ClassAttributes.svelte'
|
||||
import ClassHierarchy from './ClassHierarchy.svelte'
|
||||
import { clearSettingsStore } from '../store'
|
||||
|
||||
export let ofClass: Ref<Class<Obj>> | undefined = undefined
|
||||
export let attributeMapper:
|
||||
@ -125,6 +126,7 @@
|
||||
{ofClass}
|
||||
on:select={(e) => {
|
||||
_class = e.detail
|
||||
clearSettingsStore()
|
||||
}}
|
||||
/>
|
||||
</NavGroup>
|
||||
|
@ -25,14 +25,16 @@
|
||||
Type
|
||||
} from '@hcengineering/core'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { Card, getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, Component, DropdownLabelsIntl, EditBox, Label } from '@hcengineering/ui'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, Component, DropdownLabelsIntl, ModernEditbox, Label, Modal } from '@hcengineering/ui'
|
||||
import { DropdownIntlItem } from '@hcengineering/ui/src/types'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import setting from '../plugin'
|
||||
import view from '@hcengineering/view'
|
||||
import { clearSettingsStore } from '../store'
|
||||
|
||||
export let _id: Ref<Class<Type<PropertyType>>> | undefined = undefined
|
||||
export let _class: Ref<Class<Doc>>
|
||||
|
||||
let name: string
|
||||
let type: Type<PropertyType> | undefined
|
||||
let index: IndexKind | undefined
|
||||
@ -40,7 +42,6 @@
|
||||
let is: AnyComponent | undefined
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function save (): Promise<void> {
|
||||
if (type === undefined) return
|
||||
@ -57,7 +58,7 @@
|
||||
data.index = index
|
||||
}
|
||||
await client.createDoc(core.class.Attribute, core.space.Model, data)
|
||||
dispatch('close')
|
||||
clearSettingsStore()
|
||||
}
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
@ -95,44 +96,49 @@
|
||||
index = e.detail?.index
|
||||
defaultValue = e.detail?.defaultValue
|
||||
}
|
||||
|
||||
$: clazz = client.getHierarchy().getClass(_class)
|
||||
</script>
|
||||
|
||||
<Card
|
||||
<Modal
|
||||
label={setting.string.CreatingAttribute}
|
||||
type={'type-aside'}
|
||||
okLabel={presentation.string.Create}
|
||||
okAction={save}
|
||||
canSave={!(type === undefined || name === undefined || name.trim().length === 0)}
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
onCancel={() => {
|
||||
clearSettingsStore()
|
||||
}}
|
||||
on:changeContent
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<div class="flex-row-center">
|
||||
<Label label={setting.string.CreatingAttribute} />
|
||||
<div class="p-1">></div>
|
||||
<Label label={clazz.label} />
|
||||
<div class="hulyModal-content__titleGroup">
|
||||
<div class="hulyChip-item font-medium-12">
|
||||
<Label label={setting.string.Custom} />
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<div class="mb-2"><EditBox bind:value={name} placeholder={core.string.Name} /></div>
|
||||
<div class="flex-col mb-2">
|
||||
<div class="flex-row-center flex-grow">
|
||||
<Label label={setting.string.Type} />
|
||||
<div class="ml-4">
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
width="8rem"
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelection}
|
||||
/>
|
||||
</div>
|
||||
<ModernEditbox bind:value={name} label={core.string.Name} size={'large'} kind={'ghost'} />
|
||||
</div>
|
||||
<div class="hulyModal-content__settingsSet">
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.Type} />
|
||||
</span>
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
size={'large'}
|
||||
width="8rem"
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelection}
|
||||
/>
|
||||
</div>
|
||||
{#if is}
|
||||
<div class="flex mt-4">
|
||||
<Component {is} on:change={handleChange} />
|
||||
</div>
|
||||
<Component
|
||||
{is}
|
||||
props={{
|
||||
type,
|
||||
defaultValue,
|
||||
kind: 'regular',
|
||||
size: 'large'
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</Card>
|
||||
</Modal>
|
||||
|
@ -15,19 +15,20 @@
|
||||
<script lang="ts">
|
||||
import core, { AnyAttribute, Class, DocumentUpdate, IndexKind, PropertyType, Ref, Type } from '@hcengineering/core'
|
||||
import { getEmbeddedLabel, translate } from '@hcengineering/platform'
|
||||
import presentation, { Card, getClient } from '@hcengineering/presentation'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import setting from '../plugin'
|
||||
import {
|
||||
AnyComponent,
|
||||
Component,
|
||||
DropdownIntlItem,
|
||||
DropdownLabelsIntl,
|
||||
EditBox,
|
||||
ModernEditbox,
|
||||
Label,
|
||||
themeStore
|
||||
themeStore,
|
||||
Modal
|
||||
} from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { clearSettingsStore } from '../store'
|
||||
|
||||
export let attribute: AnyAttribute
|
||||
export let exist: boolean
|
||||
@ -39,7 +40,6 @@
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
translate(attribute.label, {}, $themeStore.language).then((p) => (name = p))
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
}
|
||||
}
|
||||
await client.updateDoc(attribute._class, attribute.space, attribute._id, update)
|
||||
dispatch('close')
|
||||
clearSettingsStore()
|
||||
}
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
@ -101,46 +101,54 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card
|
||||
<Modal
|
||||
label={setting.string.EditAttribute}
|
||||
type={'type-aside'}
|
||||
okLabel={presentation.string.Save}
|
||||
okAction={save}
|
||||
canSave={!(name === undefined || name.trim().length === 0)}
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
onCancel={() => {
|
||||
clearSettingsStore()
|
||||
}}
|
||||
on:changeContent
|
||||
>
|
||||
<div class="mb-2"><EditBox bind:value={name} placeholder={core.string.Name} /></div>
|
||||
<div class="flex-col mb-2">
|
||||
<div class="flex-row-center flex-grow">
|
||||
<Label label={setting.string.Type} />
|
||||
<div class="ml-4">
|
||||
{#if exist}
|
||||
<Label label={attribute.type.label} />
|
||||
{:else}
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
width="8rem"
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelect}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if is}
|
||||
<div class="flex mt-4">
|
||||
<Component
|
||||
{is}
|
||||
props={{
|
||||
type,
|
||||
defaultValue,
|
||||
editable: !exist
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
<div class="hulyModal-content__titleGroup">
|
||||
{#if attribute.isCustom}
|
||||
<div class="hulyChip-item font-medium-12">
|
||||
<Label label={setting.string.Custom} />
|
||||
</div>
|
||||
{/if}
|
||||
<ModernEditbox bind:value={name} label={core.string.Name} size={'large'} kind={'ghost'} />
|
||||
</div>
|
||||
</Card>
|
||||
<div class="hulyModal-content__settingsSet">
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.Type} />
|
||||
</span>
|
||||
{#if exist}
|
||||
<Label label={attribute.type.label} />
|
||||
{:else}
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
size={'large'}
|
||||
width="8rem"
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelect}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if is}
|
||||
<Component
|
||||
{is}
|
||||
props={{
|
||||
type,
|
||||
defaultValue,
|
||||
editable: !exist,
|
||||
kind: 'regular',
|
||||
size: 'large'
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</Modal>
|
||||
|
@ -36,7 +36,8 @@
|
||||
NavGroup
|
||||
} from '@hcengineering/ui'
|
||||
import { NavFooter } from '@hcengineering/workbench-resources'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { ComponentType, onDestroy } from 'svelte'
|
||||
import { settingsStore, clearSettingsStore, type SettingsStore } from '../store'
|
||||
|
||||
export let visibleNav: boolean = true
|
||||
export let navFloat: boolean = false
|
||||
@ -47,6 +48,8 @@
|
||||
|
||||
let categories: SettingsCategory[] = []
|
||||
const account = getCurrentAccount() as PersonAccount
|
||||
let asideComponent: ComponentType | null = null
|
||||
let asideProps: object | null = null
|
||||
|
||||
const settingsQuery = createQuery()
|
||||
settingsQuery.query(
|
||||
@ -72,6 +75,7 @@
|
||||
return categories.find((x) => x.name === name)
|
||||
}
|
||||
function selectCategory (id: string): void {
|
||||
clearSettingsStore()
|
||||
const loc = getCurrentResolvedLocation()
|
||||
if (loc.path[3] === id) {
|
||||
loc.path.length = 3
|
||||
@ -102,6 +106,12 @@
|
||||
showPopup(login.component.InviteLink, {})
|
||||
}
|
||||
|
||||
const updatedStore = (ss: SettingsStore): ComponentType | null => {
|
||||
asideProps = ss.props ?? null
|
||||
return ss.component ?? null
|
||||
}
|
||||
$: asideComponent = updatedStore($settingsStore)
|
||||
|
||||
defineSeparators('setting', settingsSeparators)
|
||||
</script>
|
||||
|
||||
@ -165,7 +175,7 @@
|
||||
<Separator name={'setting'} float={navFloat} index={0} color={'transparent'} />
|
||||
{/if}
|
||||
|
||||
<div class="antiPanel-component filledNav">
|
||||
<div class="antiPanel-component filledNav" style:flex-direction={'row'}>
|
||||
{#if category}
|
||||
<Component
|
||||
is={category.component}
|
||||
@ -177,15 +187,25 @@
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if asideComponent != null}
|
||||
<Separator name={'setting'} index={1} color={'transparent'} />
|
||||
<div class="hulySidePanel-container">
|
||||
{#key asideProps}
|
||||
<svelte:component this={asideComponent} {...asideProps} />
|
||||
{/key}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.hulyPanels-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-color: var(--theme-navpanel-color); // var(--global-surface-01-BackgroundColor);
|
||||
border-radius: 0 var(--small-focus-BorderRadius) var(--small-focus-BorderRadius) 0;
|
||||
|
||||
// .antiPanel-navigator {
|
||||
// background-color: transparent;
|
||||
@ -208,4 +228,13 @@
|
||||
line-height: 1.5rem;
|
||||
color: var(--global-primary-TextColor);
|
||||
}
|
||||
.hulySidePanel-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 10rem;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
border-radius: 0 var(--small-focus-BorderRadius) var(--small-focus-BorderRadius) 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -26,6 +26,7 @@
|
||||
NavItem
|
||||
} from '@hcengineering/ui'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { clearSettingsStore } from '../store'
|
||||
|
||||
export let kind: 'navigation' | 'content' | undefined
|
||||
export let categoryName: string
|
||||
@ -62,6 +63,7 @@
|
||||
)
|
||||
|
||||
function selectCategory (id: string): void {
|
||||
clearSettingsStore()
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path[3] = categoryName
|
||||
if (loc.path[4] === id) {
|
||||
|
@ -20,9 +20,12 @@
|
||||
import view from '@hcengineering/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import setting from '../../plugin'
|
||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
|
||||
export let type: ArrOf<Doc> | undefined
|
||||
export let editable: boolean = true
|
||||
export let kind: ButtonKind = 'regular'
|
||||
export let size: ButtonSize = 'medium'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
@ -56,34 +59,34 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex-col">
|
||||
<div class="flex-row-center flex-grow">
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.Type} />
|
||||
<div class="ml-4">
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl
|
||||
label={core.string.Class}
|
||||
items={types.map((p) => {
|
||||
return { id: p._id, label: p.label }
|
||||
})}
|
||||
width="8rem"
|
||||
bind:selected={refClass}
|
||||
/>
|
||||
{:else if selected}
|
||||
<Label label={selected.label} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if selected}
|
||||
<div class="flex mt-4">
|
||||
<Component
|
||||
is={getComponent(selected)}
|
||||
props={{
|
||||
type: type?.of,
|
||||
editable
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</span>
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl
|
||||
label={core.string.Class}
|
||||
{kind}
|
||||
{size}
|
||||
items={types.map((p) => {
|
||||
return { id: p._id, label: p.label }
|
||||
})}
|
||||
width="8rem"
|
||||
bind:selected={refClass}
|
||||
/>
|
||||
{:else if selected}
|
||||
<Label label={selected.label} />
|
||||
{/if}
|
||||
</div>
|
||||
{#if selected}
|
||||
<Component
|
||||
is={getComponent(selected)}
|
||||
props={{
|
||||
type: type?.of,
|
||||
editable,
|
||||
kind,
|
||||
size
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
{/if}
|
||||
|
@ -19,9 +19,12 @@
|
||||
import { DropdownLabelsIntl, Label, DropdownIntlItem } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import setting from '../../plugin'
|
||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
|
||||
export let type: DateType | undefined
|
||||
export let editable: boolean = true
|
||||
export let kind: ButtonKind = 'regular'
|
||||
export let size: ButtonSize = 'medium'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const items: DropdownIntlItem[] = [
|
||||
@ -49,22 +52,23 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center">
|
||||
<Label label={setting.string.DateMode} />
|
||||
<div class="ml-2">
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl
|
||||
{selected}
|
||||
{items}
|
||||
size="medium"
|
||||
label={setting.string.DateMode}
|
||||
on:selected={(res) => {
|
||||
selected = res.detail
|
||||
dispatch('change', { type: TypeDate(res.detail._id) })
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<Label {label} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.DateMode} />
|
||||
</span>
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl
|
||||
{selected}
|
||||
{items}
|
||||
{kind}
|
||||
{size}
|
||||
label={setting.string.DateMode}
|
||||
on:selected={(res) => {
|
||||
selected = res.detail
|
||||
dispatch('change', { type: TypeDate(res.detail._id) })
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<Label {label} />
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -23,8 +23,8 @@
|
||||
getFocusManager,
|
||||
TooltipAlignment
|
||||
} from '@hcengineering/ui'
|
||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
import EnumPopup from './EnumPopup.svelte'
|
||||
|
||||
import core, { Ref, Class, DocumentQuery, Enum } from '@hcengineering/core'
|
||||
import { ObjectCreate } from '@hcengineering/presentation'
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
export let focus = false
|
||||
export let create: ObjectCreate | undefined = undefined
|
||||
export let labelDirection: TooltipAlignment | undefined = undefined
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
export let size: ButtonSize = 'small'
|
||||
|
||||
const _class: Ref<Class<Enum>> = core.class.Enum
|
||||
const query: DocumentQuery<Enum> = {}
|
||||
@ -66,8 +68,8 @@
|
||||
{focus}
|
||||
{focusIndex}
|
||||
icon={IconFolder}
|
||||
size={'small'}
|
||||
kind={'no-border'}
|
||||
{size}
|
||||
{kind}
|
||||
showTooltip={{ label, direction: labelDirection }}
|
||||
on:click={handleClick}
|
||||
>
|
||||
|
@ -17,6 +17,7 @@
|
||||
import { TypeEnum } from '@hcengineering/model'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { Button, Label, showPopup } from '@hcengineering/ui'
|
||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
import { EnumEditor } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import setting from '../../plugin'
|
||||
@ -26,6 +27,8 @@
|
||||
export let editable: boolean = true
|
||||
export let value: Enum | undefined
|
||||
export let defaultValue: string | undefined
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
export let size: ButtonSize = 'small'
|
||||
|
||||
const client = getClient()
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -55,45 +58,45 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="flex-row-center flex-grow">
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={core.string.Enum} />
|
||||
<div class="ml-4">
|
||||
{#if editable}
|
||||
<EnumSelect label={core.string.Enum} bind:value {create} />
|
||||
{:else if value}
|
||||
{value.name}
|
||||
{/if}
|
||||
</div>
|
||||
</span>
|
||||
<div class="flex-row-center gap-2">
|
||||
{#if editable}
|
||||
<EnumSelect label={core.string.Enum} bind:value {create} {kind} {size} />
|
||||
{:else if value}
|
||||
{value.name}
|
||||
{/if}
|
||||
{#if value}
|
||||
<div class="ml-2">
|
||||
<Button
|
||||
icon={setting.icon.Setting}
|
||||
kind={'no-border'}
|
||||
size={'small'}
|
||||
showTooltip={{ label: presentation.string.Edit }}
|
||||
on:click={edit}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
icon={setting.icon.Setting}
|
||||
{kind}
|
||||
{size}
|
||||
showTooltip={{ label: presentation.string.Edit }}
|
||||
on:click={edit}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if value && type}
|
||||
<div class="flex-row-center mt-2">
|
||||
<Label label={setting.string.DefaultValue} />
|
||||
<div class="ml-2">
|
||||
<EnumEditor
|
||||
label={setting.string.SelectAValue}
|
||||
kind={'no-border'}
|
||||
size={'small'}
|
||||
allowDeselect
|
||||
{type}
|
||||
value={defaultValue ?? ''}
|
||||
onChange={(e) => {
|
||||
defaultValue = e
|
||||
dispatch('change', { type, defaultValue })
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if value && type}
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.DefaultValue} />
|
||||
</span>
|
||||
<div class="ml-2">
|
||||
<EnumEditor
|
||||
label={setting.string.SelectAValue}
|
||||
{kind}
|
||||
{size}
|
||||
allowDeselect
|
||||
{type}
|
||||
value={defaultValue ?? ''}
|
||||
onChange={(e) => {
|
||||
defaultValue = e
|
||||
dispatch('change', { type, defaultValue })
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -19,9 +19,12 @@
|
||||
import { DropdownLabelsIntl, Label } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
|
||||
export let type: RefTo<Doc> | undefined
|
||||
export let editable: boolean = true
|
||||
export let kind: ButtonKind = 'regular'
|
||||
export let size: ButtonSize = 'medium'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
@ -48,13 +51,13 @@
|
||||
$: refClass && dispatch('change', { type: TypeRef(refClass) })
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center flex-grow">
|
||||
<Label label={core.string.Class} />
|
||||
<div class="ml-4">
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl label={core.string.Class} items={classes} width="8rem" bind:selected={refClass} />
|
||||
{:else if selected}
|
||||
<Label label={selected.label} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={core.string.Class} />
|
||||
</span>
|
||||
{#if editable}
|
||||
<DropdownLabelsIntl label={core.string.Class} items={classes} width="8rem" bind:selected={refClass} {kind} {size} />
|
||||
{:else if selected}
|
||||
<Label label={selected.label} />
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -0,0 +1,131 @@
|
||||
<!--
|
||||
// Copyright © 2022 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import { DropdownIntlItem } from '@hcengineering/ui/src/types'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import view from '@hcengineering/view'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
const descendants = hierarchy.getDescendants(core.class.Type)
|
||||
const res: DropdownIntlItem[] = []
|
||||
for (const descendant of descendants) {
|
||||
const _class = hierarchy.getClass(descendant)
|
||||
if (_class.label !== undefined && hierarchy.hasMixin(_class, view.mixin.ObjectEditor)) {
|
||||
res.push({
|
||||
label: _class.label,
|
||||
id: _class._id
|
||||
})
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
const items = getTypes()
|
||||
|
||||
const handleSelection = (id: string | number) => {
|
||||
dispatch('close', id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="hulyPopupMenu-container">
|
||||
<div class="hulyPopupMenu-group">
|
||||
{#each items as item}
|
||||
<button
|
||||
class="hulyPopupMenu-group__item"
|
||||
on:click={() => {
|
||||
handleSelection(item.id)
|
||||
}}
|
||||
>
|
||||
<span class="hulyPopupMenu-group__item-label overflow-label">
|
||||
<Label label={item.label} />
|
||||
</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.hulyPopupMenu-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-shrink: 0;
|
||||
width: 15rem;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-color: var(--global-popover-BackgroundColor);
|
||||
border: 1px solid var(--global-popover-BorderColor);
|
||||
border-radius: var(--medium-BorderRadius);
|
||||
|
||||
.hulyPopupMenu-group {
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
gap: var(--spacing-0_25);
|
||||
padding: var(--spacing-0_5);
|
||||
|
||||
&__item {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border: 2px solid transparent;
|
||||
border-radius: var(--extra-small-focus-BorderRadius);
|
||||
outline: 2px solid transparent;
|
||||
|
||||
&.submenu {
|
||||
padding: var(--spacing-1_5) var(--spacing-1_5) var(--spacing-1_5) var(--spacing-2);
|
||||
}
|
||||
&:not(.submenu) {
|
||||
padding: var(--spacing-1_5) var(--spacing-2);
|
||||
}
|
||||
|
||||
&-icon {
|
||||
flex-shrink: 0;
|
||||
width: var(--global-min-Size);
|
||||
height: var(--global-min-Size);
|
||||
color: var(--global-on-accent-TextColor);
|
||||
}
|
||||
&-label {
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
color: var(--global-on-accent-TextColor);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--global-popover-hover-BackgroundColor);
|
||||
}
|
||||
&:focus {
|
||||
background-color: var(--global-popover-hover-BackgroundColor);
|
||||
border-color: var(--global-focus-inset-BorderColor);
|
||||
outline-color: var(--global-focus-BorderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -50,6 +50,7 @@ import ClassAttributes from './components/ClassAttributes.svelte'
|
||||
import ClassAttributesList from './components/ClassAttributesList.svelte'
|
||||
|
||||
export { ClassSetting, filterDescendants, ClassAttributes, ClassAttributesList }
|
||||
export * from './store'
|
||||
|
||||
async function DeleteMixin (object: Mixin<Class<Doc>>): Promise<void> {
|
||||
const docs = await getClient().findAll(object._id, {}, { limit: 1 })
|
||||
|
37
plugins/setting-resources/src/store.ts
Normal file
37
plugins/setting-resources/src/store.ts
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright © 2022 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type ComponentType } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface SettingsStore {
|
||||
component?: ComponentType | null
|
||||
props?: object | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const settingsStore = writable<SettingsStore>({})
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const clearSettingsStore = (): void => {
|
||||
settingsStore.set({ component: null, props: null })
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
import { onDestroy } from 'svelte'
|
||||
import Types from './Types.svelte'
|
||||
import { Resource } from '@hcengineering/platform'
|
||||
import { clearSettingsStore } from '@hcengineering/setting-resources'
|
||||
|
||||
export let kind: 'navigation' | 'tools' | undefined
|
||||
export let categoryName: string
|
||||
@ -37,6 +38,7 @@
|
||||
)
|
||||
|
||||
function selectProjectType (id: string): void {
|
||||
clearSettingsStore()
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path[3] = categoryName
|
||||
loc.path[4] = id
|
||||
|
Loading…
Reference in New Issue
Block a user