Merge pull request #3957 from penpot/eva-remove-new-css-phase-3

♻️ Remove new-css-system phase 3
This commit is contained in:
Alejandro 2024-01-04 10:37:35 +01:00 committed by GitHub
commit c77af2000c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 4966 additions and 15094 deletions

View File

@ -216,6 +216,7 @@
.button-disabled { .button-disabled {
@include buttonStyle; @include buttonStyle;
@include flexCenter; @include flexCenter;
height: $s-32;
background-color: var(--button-background-color-disabled); background-color: var(--button-background-color-disabled);
border: $s-1 solid var(--button-border-color-disabled); border: $s-1 solid var(--button-border-color-disabled);
color: var(--button-foreground-color-disabled); color: var(--button-foreground-color-disabled);
@ -738,7 +739,6 @@
@include titleTipography; @include titleTipography;
color: var(--color-foreground-primary); color: var(--color-foreground-primary);
text-align: left; text-align: left;
display: grid; display: grid;
grid-template-columns: 1fr 22px; grid-template-columns: 1fr 22px;
grid-template-areas: "name button"; grid-template-areas: "name button";

View File

@ -305,6 +305,11 @@
--resize-area-background-color: var(--color-background-primary); --resize-area-background-color: var(--color-background-primary);
--resize-area-border-color: var(--color-background-quaternary); --resize-area-border-color: var(--color-background-quaternary);
--flow-tag-background-color: var(--color-background-tertiary);
--flow-tag-foreground-color: var(--color-foreground-secondary);
--flow-tag-background-color-hover: var(--color-accent-primary);
--flow-tag-foreground-color-hover: var(--color-background-primary);
// VIEWER // VIEWER
--viewer-background-color: var(--color-background-secondary); --viewer-background-color: var(--color-background-secondary);
--viewer-paginator-background-color: var(--color-background-tertiary); --viewer-paginator-background-color: var(--color-background-tertiary);

View File

@ -44,7 +44,6 @@
//################################################# //#################################################
@import "common/framework"; @import "common/framework";
@import "main/partials/modal";
@import "main/partials/forms"; @import "main/partials/forms";
@import "main/partials/texts"; @import "main/partials/texts";
@import "main/partials/context-menu"; @import "main/partials/context-menu";
@ -58,26 +57,16 @@
@import "main/partials/viewer-header"; @import "main/partials/viewer-header";
@import "main/partials/viewer-thumbnails"; @import "main/partials/viewer-thumbnails";
@import "main/partials/activity-bar"; @import "main/partials/activity-bar";
@import "main/partials/dashboard";
@import "main/partials/dashboard-header";
@import "main/partials/dashboard-grid";
@import "main/partials/dashboard-sidebar";
@import "main/partials/dashboard-team";
@import "main/partials/dashboard-settings";
@import "main/partials/dashboard-fonts";
@import "main/partials/debug-icons-preview"; @import "main/partials/debug-icons-preview";
@import "main/partials/editable-label"; @import "main/partials/editable-label";
@import "main/partials/loader"; @import "main/partials/loader";
@import "main/partials/project-bar"; @import "main/partials/project-bar";
@import "main/partials/sidebar"; @import "main/partials/sidebar";
@import "main/partials/sidebar-document-history";
@import "main/partials/tab-container"; @import "main/partials/tab-container";
@import "main/partials/tool-bar"; @import "main/partials/tool-bar";
@import "main/partials/user-settings"; @import "main/partials/user-settings";
@import "main/partials/workspace"; @import "main/partials/workspace";
@import "main/partials/comments";
@import "main/partials/color-bullet"; @import "main/partials/color-bullet";
@import "main/partials/inspect"; @import "main/partials/inspect";
@import "main/partials/exception-page"; @import "main/partials/exception-page";
@import "main/partials/share-link";
@import "main/partials/signup-questions"; @import "main/partials/signup-questions";

View File

@ -1,467 +0,0 @@
.comments-section {
.thread-bubble {
position: absolute;
display: flex;
transform: translate(-15px, -15px);
cursor: pointer;
pointer-events: auto;
background-color: $color-gray-10;
color: $color-gray-60;
border: 1px solid #b1b2b5;
box-sizing: border-box;
box-shadow: 0px 4px 4px rgba($color-black, 0.25);
font-size: $fs12;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
&.resolved {
color: $color-gray-10;
background-color: $color-gray-50;
}
&.unread {
background-color: $color-primary;
}
span {
user-select: none;
}
}
.thread-content {
position: absolute;
pointer-events: auto;
margin-left: 10px;
background: $color-white;
border: 1px solid $color-gray-20;
box-sizing: border-box;
box-shadow: 0px 2px 8px rgba($color-black, 0.25);
border-radius: $br2;
min-width: 280px;
max-width: 280px;
user-select: text;
.comments {
max-height: 420px;
min-height: 105px;
overflow-y: auto;
}
hr {
border: 0;
height: 1px;
background-color: $color-gray-20;
margin: 0px 10px;
}
}
.reply-form {
display: flex;
padding: 10px;
flex-direction: column;
&.edit-form {
padding-bottom: 0px;
}
textarea {
font-family: "worksans", sans-serif;
font-size: $fs12;
min-height: 32px;
outline: none;
overflow: hidden;
padding: $size-2;
resize: none;
width: 100%;
border-radius: $br2;
border: 1px solid $color-gray-20;
max-height: 4rem;
}
.buttons {
margin-top: 10px;
display: flex;
justify-content: flex-end;
input {
margin: 0px;
font-size: $fs14;
&:not(:last-child) {
margin-right: 6px;
}
}
}
}
.comment-container {
position: relative;
}
.comment {
display: flex;
flex-direction: column;
padding: $size-4 $size-2;
.author {
display: flex;
align-items: center;
height: 26px;
max-height: 26px;
position: relative;
.name {
display: flex;
flex-direction: column;
.fullname {
font-weight: $fw700;
color: $color-gray-60;
font-size: $fs12;
@include text-ellipsis;
width: 174px;
}
.timeago {
margin-top: -2px;
font-size: $fs12;
color: $color-gray-30;
}
}
.avatar {
display: flex;
align-items: center;
padding-right: 6px;
img {
border-radius: 50%;
flex-shrink: 0;
height: 24px;
width: 24px;
}
}
.options-resolve {
position: absolute;
right: 20px;
top: 0px;
width: 16px;
height: 16px;
cursor: pointer;
svg {
width: 16px;
height: 16px;
fill: $color-gray-30;
}
}
.options {
position: absolute;
right: -2px;
top: 2px;
height: 16px;
display: flex;
align-items: center;
cursor: pointer;
.options-icon {
svg {
width: 14px;
height: 14px;
fill: $color-black;
}
}
}
}
.content {
margin: $size-4 0;
font-size: $fs14;
color: $color-black;
.text {
margin: 0 $size-2 0 26px;
white-space: pre-wrap;
display: inline-block;
word-break: break-word;
}
}
}
.comment-options-dropdown {
top: 7px;
right: 7px;
width: 150px;
border: 1px solid #b1b2b5;
}
}
.workspace-comment-threads-sidebar-header {
display: flex;
background-color: $color-black;
height: 34px;
align-items: center;
padding: 0px 9px;
color: $color-gray-10;
font-size: $fs12;
justify-content: space-between;
.options {
display: flex;
margin-right: 3px;
cursor: pointer;
.label {
padding-right: 8px;
}
.icon {
display: flex;
align-items: center;
}
svg {
fill: $color-gray-10;
width: 10px;
height: 10px;
}
}
.dropdown {
top: 80px;
right: 7px;
}
}
.comment-threads-section {
pointer-events: auto;
.thread-groups {
height: calc(100% - 34px);
overflow-y: scroll;
hr {
border: 0;
height: 1px;
background-color: $color-gray-30;
margin: 0px 0px;
}
}
.thread-group {
display: flex;
flex-direction: column;
font-size: $fs12;
.section-title {
margin: 0px 10px;
margin-top: 15px;
.icon {
margin-right: 4px;
}
.label {
&.filename {
font-weight: $fw700;
}
}
svg {
fill: $color-gray-10;
height: 10px;
width: 10px;
}
}
}
.thread-bubble {
position: unset;
transform: unset;
width: 24px;
height: 24px;
margin-right: 6px;
box-shadow: unset;
}
.comment {
cursor: pointer;
.author {
margin-bottom: $size-4;
.name {
display: flex;
.fullname {
width: unset;
max-width: 170px;
color: $color-gray-20;
padding-right: 3px;
}
.timeago {
margin-top: unset;
color: $color-gray-20;
}
}
}
.content {
margin-top: 0px;
color: $color-white;
&.replies {
margin: 0 $size-2 0 26px;
display: flex;
.total-replies {
margin-right: 9px;
color: $color-info;
}
.new-replies {
color: $color-primary;
}
}
}
}
}
.viewer-comments-container {
width: 100%;
height: 100%;
z-index: 1;
position: absolute;
top: 0px;
left: 0px;
}
.workspace-comments-container {
width: 100%;
height: 100%;
grid-column: 1 / span 2;
grid-row: 1 / span 2;
z-index: 1000;
pointer-events: none;
overflow: hidden;
user-select: text;
.threads {
position: absolute;
top: 0px;
left: 0px;
}
}
.dashboard-comments-section {
width: 25px;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
background-color: $color-dashboard;
border-radius: $br3;
position: relative;
.button {
width: 25px;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
background-color: $color-dashboard;
border-radius: $br3;
svg {
width: 15px;
height: 15px;
}
&.unread {
background-color: $color-warning;
}
&.open {
background-color: $color-black;
svg {
fill: $color-primary;
}
}
}
.dropdown {
width: 280px;
bottom: 35px;
left: 0px;
border-radius: $br3;
}
.header {
display: flex;
height: 40px;
align-items: center;
padding: 0px 11px;
h3 {
font-weight: $fw400;
color: $color-black;
font-size: $fs14;
line-height: $lh-128; // Original value was $fs18 => 1.125rem = 18px; 18px/14px = 128.571428571% => $lh-128 (rounded)
flex-grow: 1;
}
.close {
display: flex;
align-items: center;
}
svg {
width: 15px;
height: 15px;
transform: rotate(45deg);
}
}
.thread-groups {
max-height: calc(30rem - 40px);
overflow: auto;
hr {
background-color: $color-gray-10;
}
}
.thread-group .section-title {
color: $color-black;
}
.comment {
.author .name .fullname {
color: $color-gray-40;
}
.content {
color: $color-black;
}
}
}
.thread-groups-placeholder {
align-items: center;
display: flex;
flex-direction: column;
font-size: $fs12;
padding: $size-5;
text-align: center;
svg {
fill: $color-gray-20;
height: 24px;
margin-bottom: $size-5;
width: 24px;
}
}

View File

@ -1,254 +0,0 @@
.dashboard-fonts {
display: flex;
flex-direction: column;
align-items: center;
.dashboard-installed-fonts {
max-width: 1000px;
width: 100%;
display: flex;
margin-top: $size-5;
flex-direction: column;
h3 {
font-size: $fs14;
color: $color-gray-30;
margin: $size-1;
}
.font-item {
color: $color-black;
}
}
.installed-fonts-header {
color: $color-gray-40;
display: flex;
height: 40px;
font-size: $fs12;
background-color: $color-white;
align-items: center;
padding: 0px $size-5;
> .family {
min-width: 200px;
width: 200px;
}
> .variants {
padding-left: 12px;
}
.search-input {
display: flex;
flex-grow: 1;
justify-content: flex-end;
input {
font-size: $fs12;
border: 1px solid $color-gray-30;
border-radius: $br3;
width: 130px;
padding: $size-1;
margin: 0px;
}
}
}
.font-item {
color: $color-gray-40;
font-size: $fs14;
background-color: $color-white;
display: flex;
max-width: 1000px;
width: 100%;
min-height: 97px;
align-items: center;
padding: $size-5;
justify-content: space-between;
&:not(:first-child) {
border-top: 1px solid $color-gray-10;
}
input {
border: 1px solid $color-gray-30;
border-radius: $br3;
margin: 0px;
padding: $size-2;
font-size: $fs12;
}
> .family {
min-width: 200px;
width: 200px;
}
> .filenames {
min-width: 200px;
}
> .variants {
font-size: $fs14;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
.variant {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
cursor: pointer;
.icon {
display: flex;
height: 16px;
width: 16px;
margin-left: 6px;
align-items: center;
svg {
fill: transparent;
width: 12px;
height: 12px;
transform: rotate(45deg);
}
}
&:hover {
.icon svg {
fill: $color-gray-30;
}
}
}
}
.filenames {
display: flex;
flex-direction: column;
font-size: $fs12;
}
.options {
display: flex;
justify-content: flex-end;
min-width: 180px;
.icon {
width: $size-5;
cursor: pointer;
display: flex;
margin-left: 10px;
justify-content: center;
align-items: center;
&.failure {
margin-right: 10px;
svg {
fill: $color-warning;
}
}
svg {
width: 16px;
height: 16px;
}
&.close {
svg {
transform: rotate(45deg);
}
}
}
}
}
.dashboard-fonts-upload {
max-width: 1000px;
width: 100%;
display: flex;
flex-direction: column;
.upload-button {
width: 100px;
}
.btn-secondary {
margin-left: 10px;
}
}
.dashboard-fonts-hero {
font-size: $fs14;
padding: $size-6;
background-color: $color-white;
margin-top: $size-6;
display: flex;
justify-content: space-between;
.banner {
background-color: $color-info-lighter;
display: grid;
grid-template-columns: 40px 1fr;
&:not(:last-child) {
margin-bottom: 10px;
}
.icon {
display: flex;
align-items: flex-start;
justify-content: center;
padding-top: 10px;
background-color: $color-info;
svg {
fill: $color-white;
}
}
.content {
margin: 10px;
}
&.warning {
background-color: $color-warning-lighter;
.icon {
background-color: $color-warning;
}
}
}
.desc {
h2 {
margin-bottom: $size-4;
color: $color-black;
}
width: 80%;
color: $color-gray-40;
}
.btn-primary {
flex-shrink: 0;
}
}
.fonts-placeholder {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
max-width: 1000px;
width: 100%;
height: 161px;
border: 1px dashed $color-gray-20;
margin-top: 16px;
.icon {
svg {
fill: $color-gray-40;
width: 32px;
height: 32px;
}
}
.label {
color: $color-gray-40;
font-size: $fs14;
}
}
}

View File

@ -1,527 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.dashboard-grid {
font-size: $fs14;
height: 100%;
overflow: hidden;
overflow-y: auto;
margin-bottom: 0;
.grid-row {
display: grid;
width: 99%;
margin-left: 13px;
}
.grid-item {
align-items: center;
cursor: pointer;
display: flex;
flex-direction: column;
flex: 1 0 260px;
height: 230px;
margin: $size-3 $size-4 $size-4 $size-2;
position: relative;
text-align: center;
a,
button {
width: 100%;
font-weight: $fw400;
}
button {
background-color: transparent;
border: none;
}
@media #{$bp-max-1366} {
height: 200px;
flex: 1 0 230px;
}
&:hover {
.grid-item-th {
border: 2px solid $color-primary;
}
}
.grid-item-th {
border-radius: $br3;
border: 2px solid lighten($color-gray-20, 15%);
text-align: initial;
img {
object-fit: contain;
}
}
&.dragged {
border-radius: $br3;
border: 2px solid lighten($color-gray-20, 15%);
text-align: initial;
max-height: 160px;
}
&.placeholder {
min-width: 115px;
max-width: 115px;
display: flex;
flex-direction: column;
justify-content: center;
.placeholder-icon {
svg {
transform: rotate(-90deg);
width: 20px;
height: 20px;
fill: $color-gray-30;
}
}
.placeholder-label {
font-size: $fs14;
}
}
&.overlay {
border-radius: $br4;
border: 2px solid $color-primary;
height: 100%;
opacity: 0;
pointer-events: none;
position: absolute;
width: 100%;
z-index: 1;
}
&:hover .overlay {
display: block;
opacity: 1;
}
&.small-item {
max-width: 12%;
min-width: 190px;
padding: $size-4;
justify-content: center;
}
.grid-item-icon {
width: 90px;
height: 90px;
}
.info-wrapper {
display: grid;
grid-template-columns: 1fr auto;
}
.item-info {
display: grid;
padding: $size-2;
text-align: left;
width: 100%;
font-size: $fs12;
h3 {
border: 1px solid transparent;
color: $color-gray-60;
font-size: $fs14;
font-weight: $fw500;
overflow: hidden;
padding: 0;
height: 27px;
padding-right: $size-2;
text-overflow: ellipsis;
width: 100%;
white-space: nowrap;
line-height: $lh-192; // Original value was 27px; 27px/14px = 192.857142857% => $lh-192 (rounded)
max-width: 260px;
@media #{$bp-max-1366} {
max-width: 230px;
}
}
span.date {
color: $color-gray-30;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
white-space: nowrap;
max-width: 260px;
&::first-letter {
text-transform: capitalize;
}
@media #{$bp-max-1366} {
max-width: 230px;
}
}
.edit-wrapper {
.element-title {
padding: 0px;
height: 25px;
color: $color-gray-60;
font-size: $fs14;
font-weight: $fw400;
}
}
}
.item-badge {
background-color: $color-white;
border: 1px solid $color-gray-20;
border-radius: $br2;
position: absolute;
top: $size-2;
right: $size-2;
height: 32px;
width: 32px;
display: flex;
align-items: center;
justify-content: center;
svg {
fill: $color-gray-30;
height: 16px;
width: 16px;
}
}
&.add-file {
border: 1px dashed $color-gray-20;
justify-content: center;
box-shadow: none;
span {
color: $color-gray-60;
font-size: $fs14;
}
&:hover {
background-color: $color-white;
border: 2px solid $color-primary;
}
}
// PROJECTS, ELEMENTS & ICONS GRID
&.project-th {
background-color: $color-white;
&:hover,
&:focus,
&:focus-within {
.project-th-actions {
opacity: 1;
}
a {
text-decoration: none;
}
}
.selected {
.grid-item-th {
border: 2px solid $color-primary;
}
}
.project-th-actions {
align-items: center;
opacity: 0;
display: flex;
right: 5px;
justify-content: center;
width: 30px;
height: 100%;
span {
color: $color-black;
}
.project-th-icon {
align-items: center;
display: flex;
margin-right: $size-2;
&.menu {
margin-right: 0;
display: flex;
justify-content: center;
align-items: flex-end;
flex-direction: column;
width: 100%;
height: 30px;
margin-top: 20px;
> svg {
fill: $color-gray-60;
margin-right: 0;
height: 18px;
width: 18px;
}
&:hover,
&:focus {
> svg {
fill: $color-primary-dark;
}
}
}
}
}
.project-th-actions.force-display {
opacity: 1;
}
}
// IMAGES SECTION
&.images-th {
border: 1px dashed $color-gray-20;
border-bottom: 2px solid lighten($color-gray-20, 12%);
&:hover {
border-color: $color-primary;
}
}
.grid-item-image {
svg {
max-height: 100px;
max-width: 100px;
min-height: 40px;
min-width: 40px;
width: 8vw;
}
}
.color-swatch {
border-top-left-radius: $br5;
border-top-right-radius: $br5;
height: 25%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.color-data {
color: $color-gray-30;
margin-top: 15px;
}
.drag-counter {
position: absolute;
top: 5px;
left: 4px;
width: 32px;
height: 32px;
background-color: $color-primary;
border-radius: 50%;
color: $color-black;
font-size: $fs18;
display: flex;
justify-content: center;
align-items: center;
}
}
.grid-item-th {
background-position: center;
background-size: auto 80%;
background-repeat: no-repeat;
border-top-left-radius: $br3;
border-top-right-radius: $br3;
height: 230px;
max-height: 160px;
overflow: hidden;
position: relative;
width: 100%;
background-color: $color-canvas;
display: flex;
justify-content: center;
flex-direction: row;
.img-th {
height: auto;
width: 100%;
}
svg {
height: 100%;
width: 100%;
}
svg#loader-pencil {
fill: $color-gray-20;
}
}
// LIBRARY VIEW
.grid-item {
.library {
height: 580px;
}
&.project-th.library {
height: 610px;
width: 300px;
}
.grid-item-th.library {
background-color: $color-gray-50;
flex-direction: column;
height: 90%;
justify-content: flex-start;
max-height: 550px;
padding: $size-6;
.asset-section {
font-size: $fs12;
color: $color-gray-20;
&:not(:first-child) {
margin-top: $size-4;
}
}
.asset-title {
display: flex;
font-size: $fs12;
text-transform: uppercase;
& .num-assets {
color: $color-gray-30;
}
}
.asset-list-item {
display: flex;
align-items: center;
border: 1px solid transparent;
border-radius: $br3;
margin-top: $size-1;
padding: 2px;
font-size: $fs12;
color: $color-white;
position: relative;
& .name-block {
color: $color-gray-20;
width: calc(100% - 24px - #{$size-2});
}
& .item-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
}
& svg {
background-color: $color-canvas;
border-radius: $br4;
border: 2px solid transparent;
height: 24px;
width: 24px;
margin-right: $size-2;
}
& .color-name {
color: $color-white;
}
& .color-value {
margin-left: $size-1;
color: $color-gray-30;
text-transform: uppercase;
}
& .typography-sample {
height: 20px;
margin-right: $size-1;
width: 20px;
}
}
}
}
}
.grid-empty-placeholder {
border-radius: $br12;
display: grid;
background-color: rgba(227, 227, 227, 0.3);
padding: 13px;
margin-right: 13px;
height: 230px;
&.loader {
justify-items: center;
}
.icon {
display: flex;
align-items: center;
justify-content: center;
}
&.libs {
background-image: url(/images/ph-left.svg), url(/images/ph-right.svg);
background-position:
15% bottom,
85% top;
background-repeat: no-repeat;
align-items: center;
border: 1px dashed #b1b2b5;
border-radius: $br3;
display: flex;
flex-direction: column;
height: 200px;
margin: 1rem;
padding: 3rem;
justify-content: center;
.text {
p {
max-width: 360px;
text-align: center;
font-size: $fs16;
}
}
}
.create-new {
background-color: white;
border: 2px solid $color-gray-10;
border-radius: $br3;
color: $color-black;
cursor: pointer;
height: 158px;
font-family: "worksans", sans-serif;
margin: 0.5rem;
&:hover {
border: 2px solid $color-primary;
}
}
&.search {
align-items: center;
display: flex;
justify-content: center;
flex-direction: column;
height: 200px;
background: $color-white;
border: 1px dashed #e3e3e3;
border-radius: $br0;
}
svg {
width: 36px;
height: 36px;
fill: $color-gray-20;
}
.text {
margin-top: 10px;
color: $color-gray-30;
font-size: $fs16;
}
}

View File

@ -1,139 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.dashboard-header {
display: flex;
align-items: center;
justify-content: space-between;
background-color: $color-white;
height: 63px;
padding: $size-1 $size-4 $size-1 $size-2;
position: relative;
z-index: 10;
user-select: none;
&.team {
display: grid;
grid-template-columns: 20% 1fr 20%;
}
.element-name {
margin-right: $size-2;
}
.btn-secondary {
flex-shrink: 0;
z-index: 10;
height: 32px;
}
svg {
fill: $color-black;
height: 14px;
margin-right: $size-1;
width: 14px;
}
nav {
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 1;
ul {
display: flex;
font-size: $fs14;
justify-content: center;
margin: 0;
}
li {
a {
display: flex;
align-items: center;
flex-basis: 140px;
border-bottom: 3px solid transparent;
color: $color-gray-30;
height: 40px;
padding: $size-1 $size-5;
font-weight: $fw400;
&:hover {
color: $color-black;
text-decoration: none;
}
}
&.active {
a {
color: $color-black;
border-color: $color-primary;
}
}
}
}
.dashboard-title {
display: flex;
align-items: center;
margin-left: 13px;
h1 {
color: $color-black;
display: flex;
flex-shrink: 0;
font-size: $fs22;
font-weight: $fw600;
z-index: 10;
user-select: all;
}
.context-menu.is-open {
margin-top: 10px;
}
}
.icon {
display: flex;
align-items: center;
cursor: pointer;
margin-left: $size-2;
z-index: 10;
svg {
fill: $color-gray-40;
width: 15px;
height: 15px;
&:hover {
fill: $color-primary-dark;
}
}
}
.dashboard-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
.dashboard-header-actions {
display: flex;
}
.pin-icon {
margin: 0 $size-2 0 $size-5;
background-color: transparent;
border: none;
svg {
fill: $color-gray-20;
}
&.active {
svg {
fill: $color-gray-50;
}
}
}
}

View File

@ -1,303 +0,0 @@
// Copyright (c) 2020 KALEIDOS INC
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.dashboard-sidebar {
&.settings {
.back-to-dashboard {
padding: 12px 18px;
font-size: $fs14;
cursor: pointer;
display: flex;
.icon {
display: flex;
align-items: center;
margin-right: 14px;
}
.text {
color: $color-gray-60;
}
svg {
fill: $color-gray-60;
transform: rotate(90deg);
width: 12px;
height: 12px;
}
}
}
}
.dashboard-settings {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
.form-container {
margin-top: 50px;
display: flex;
max-width: 368px;
margin-bottom: 2rem;
width: 100%;
&.two-columns {
max-width: 536px;
justify-content: space-between;
flex-direction: row;
}
h2 {
margin-bottom: 1rem;
}
}
.avatar-form {
display: flex;
flex-direction: column;
width: 120px;
min-width: 120px;
img {
border-radius: 50%;
flex-shrink: 0;
height: 120px;
margin-right: $size-4;
width: 120px;
}
.image-change-field {
position: relative;
width: 120px;
height: 120px;
.update-overlay {
opacity: 0;
cursor: pointer;
position: absolute;
width: 121px;
height: 121px;
border-radius: 50%;
font-size: $fs24;
color: $color-white;
line-height: $lh-500; // Original value was 120px; 120px/24px = 500% => $lh-500
text-align: center;
background: $color-primary-dark;
z-index: 14;
}
input[type="file"] {
width: 120px;
height: 120px;
position: absolute;
opacity: 0;
cursor: pointer;
top: 0;
z-index: 15;
}
&:hover {
.update-overlay {
opacity: 0.8;
}
}
}
}
.profile-form {
display: flex;
flex-direction: column;
max-width: 368px;
width: 100%;
.newsletter-subs {
border-bottom: 1px solid $color-gray-20;
border-top: 1px solid $color-gray-20;
padding: 30px 0;
margin-bottom: 31px;
.newsletter-title {
font-family: "worksans", sans-serif;
color: $color-gray-30;
font-size: $fs14;
}
label {
font-family: "worksans", sans-serif;
color: $color-gray-60;
font-size: $fs12;
margin-right: -17px;
margin-bottom: 13px;
}
.info {
font-family: "worksans", sans-serif;
color: $color-gray-30;
font-size: $fs12;
margin-bottom: 8px;
}
.input-checkbox label {
align-items: flex-start;
}
}
}
.options-form,
.password-form {
h2 {
font-size: $fs14;
margin-bottom: 20px;
}
}
}
.dashboard-access-tokens {
display: flex;
flex-direction: column;
align-items: center;
.access-tokens-hero-container {
max-width: 1000px;
width: 100%;
display: flex;
flex-direction: column;
}
.access-tokens-hero {
font-size: $fs14;
padding: $size-6;
background-color: $color-white;
margin-top: $size-6;
display: flex;
justify-content: space-between;
.desc {
width: 80%;
color: $color-gray-40;
h2 {
margin-bottom: $size-4;
color: $color-black;
}
p {
font-size: $fs16;
}
}
.btn-primary {
flex-shrink: 0;
}
}
.access-tokens-empty {
text-align: center;
max-width: 1000px;
width: 100%;
padding: $size-6;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 1px dashed $color-gray-20;
color: $color-gray-40;
margin-top: 12px;
min-height: 136px;
}
.table-row {
background-color: $color-white;
display: grid;
grid-template-columns: 1fr 43% 12px;
height: 63px;
&:not(:first-child) {
margin-top: 8px;
}
}
.table-field {
&.name {
color: $color-gray-60;
}
&.expiration-date {
color: $color-gray-40;
font-size: $fs14;
.content {
padding: 2px 5px;
&.expired {
background-color: $color-warning-lighter;
border-radius: $br4;
color: $color-gray-40;
}
}
}
&.access-token-created {
word-break: break-all;
}
&.actions {
position: relative;
}
}
}
.access-tokens-modal {
.action-buttons {
gap: 10px;
.cancel-button {
border: 1px solid $color-gray-30;
background: $color-canvas;
border-radius: $br3;
padding: 0.5rem 1rem;
cursor: pointer;
margin-right: 8px;
&:hover {
background: $color-gray-20;
}
}
}
.access-token-created {
position: relative;
word-break: break-all;
.custom-input input {
background-color: $color-success-lighter;
border: 0;
padding: 0 0 0 15px;
}
}
.help-icon {
border: none;
height: 40px;
width: 40px;
position: absolute;
top: 0;
right: 0;
cursor: pointer;
background-color: $color-success-lighter;
svg {
fill: $color-gray-30;
}
&:hover {
svg {
fill: $color-gray-60;
}
}
}
.token-created-info {
font-size: $fs12;
color: $color-gray-40;
}
}

View File

@ -1,476 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.dashboard-sidebar {
background-color: $color-white;
z-index: 1;
display: flex;
flex-direction: column;
height: 100%;
padding-top: $size-2;
.sidebar-content {
display: flex;
flex-direction: column;
height: 100%;
overflow-y: auto;
padding: 0;
hr {
border-color: $color-gray-10;
margin: 1rem 15px;
}
}
.sidebar-team-switch {
position: relative;
display: flex;
margin: 5px 15px;
.teams-dropdown {
left: 0;
top: 50px;
z-index: 12;
max-height: 30rem;
min-width: 234px;
overflow-y: auto;
}
.options-dropdown {
right: 2px;
top: 50px;
z-index: 12;
max-height: 30rem;
min-width: 162px;
}
.switch-content {
height: 40px;
display: flex;
width: 100%;
border: 1px solid $color-gray-10;
border-radius: $br5;
align-items: center;
}
.switch-options {
display: flex;
max-width: 22px;
min-width: 28px;
border-left: 1px solid $color-gray-10;
justify-content: center;
align-items: center;
cursor: pointer;
background-color: transparent;
border: none;
svg {
width: 15px;
height: 13px;
fill: $color-gray-60;
}
}
.current-team {
cursor: pointer;
display: flex;
align-items: center;
flex-grow: 1;
font-size: $fs14;
padding: 0px 10px;
background-color: transparent;
border: none;
}
.team-name {
flex-grow: 1;
display: flex;
height: 40px;
align-items: center;
&.action {
.team-icon {
border-radius: 50%;
background-color: $color-gray-10;
height: 24px;
margin-right: 10px;
padding: 6px;
width: 24px;
svg {
height: 12px;
width: 12px;
}
}
&:hover {
.team-icon {
background-color: $color-primary;
}
}
.team-text {
width: 150px;
}
}
.team-icon {
display: flex;
align-items: center;
padding-right: 10px;
svg {
width: 23px;
height: 23px;
fill: $color-gray-60;
}
img {
border-radius: 50%;
flex-shrink: 0;
height: 23px;
width: 23px;
}
}
.team-text {
color: $color-gray-60;
@include text-ellipsis;
width: 130px;
text-align: left;
}
.icon {
margin-left: auto;
svg {
fill: $color-gray-60;
}
}
}
.switch-icon {
display: flex;
align-items: center;
justify-content: center;
svg {
width: 10px;
height: 10px;
fill: $color-gray-60;
}
}
}
.sidebar-empty-placeholder {
padding: 10px 12px;
color: $color-gray-30;
display: flex;
align-items: flex-start;
.icon {
padding: 0px 10px;
svg {
fill: $color-gray-30;
width: 12px;
height: 12px;
}
}
.text {
font-size: $fs12;
}
}
.sidebar-nav {
display: flex;
flex-direction: column;
overflow-y: auto;
margin: 0;
user-select: none;
// TODO: should be deprecated / unclear name
&.dashboard-common {
overflow: unset;
}
&.no-overflow {
overflow: unset;
}
& > li {
align-items: center;
cursor: pointer;
display: flex;
flex-shrink: 0;
padding: $size-2;
a {
font-weight: $fw400;
width: 100%;
&:hover {
text-decoration: none;
}
}
svg {
fill: $color-black;
margin-right: 8px;
height: $size-3;
width: $size-3;
}
span.element-title {
color: $color-gray-60;
font-size: $fs14;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&::before {
background-color: transparent;
border-radius: $br3;
content: "";
height: 26px;
margin-right: $size-2;
width: 4px;
}
&.recent-projects {
svg {
fill: $color-white;
}
}
& .edit-wrapper {
border: 1px solid $color-gray-10;
border-radius: $br3;
display: flex;
width: 100%;
}
input.element-title {
border: 0;
height: 30px;
padding: 5px;
margin: 0;
width: 100%;
background-color: $color-white;
}
.close {
background-color: $color-white;
cursor: pointer;
padding-left: 5px;
svg {
fill: $color-gray-30;
height: 15px;
transform: rotate(45deg) translateY(7px);
width: 15px;
margin: 0;
}
}
.element-subtitle {
color: $color-gray-20;
font-style: italic;
}
&:hover {
&::before {
background-color: $color-gray-10;
}
}
&.current {
a {
font-weight: $fw700;
}
&::before {
background-color: $color-primary;
}
}
&.dragging {
background-color: color.adjust($color-primary, $alpha: -0.69);
}
}
}
.sidebar-search {
align-items: center;
background-color: $color-white;
border: 1px solid $color-gray-10;
border-radius: $br5;
display: flex;
margin: 5px 15px;
.input-text {
background: transparent;
border: 0;
color: $color-gray-60;
font-size: $fs14;
padding: 6px;
margin: 0;
max-width: 195px;
width: 100%;
height: 40px;
}
&:focus,
&:focus-within {
border-color: $color-black;
}
.search,
.clear-search {
align-items: center;
cursor: pointer;
display: flex;
height: 22px;
margin-left: auto;
padding: 0 $size-2;
width: 32px;
svg {
fill: $color-gray-30;
height: 15px;
width: 15px;
}
}
.clear-search svg {
transform: rotate(45deg);
&:hover {
fill: $color-danger;
}
}
}
&.profile-bar {
background-color: $color-gray-10;
.dashboard-sidebar-inside {
display: none;
}
}
}
.projects-row {
align-items: center;
display: flex;
margin-top: 1rem;
padding: $size-2;
position: relative;
span {
color: $color-gray-30;
font-size: $fs14;
}
.btn-icon-light {
margin-left: auto;
}
&::before {
background-color: $color-gray-10;
content: "";
height: 1px;
left: 4%;
position: absolute;
right: 4%;
top: -5px;
width: 92%;
}
}
.team-form-modal {
h2 {
font-weight: $fw400;
color: $color-gray-40;
font-size: 28px;
margin-bottom: 30px;
}
.buttons-row {
margin-top: 20px;
display: flex;
justify-content: center;
}
input[type="submit"] {
margin-bottom: 0px;
}
}
.profile-section {
align-items: center;
cursor: pointer;
display: flex;
padding: 10px 15px;
position: relative;
.profile {
align-items: center;
cursor: pointer;
display: flex;
flex-grow: 1;
span {
@include text-ellipsis;
color: $color-black;
margin: 10px;
font-size: $fs14;
max-width: 160px;
}
img {
border-radius: 50%;
flex-shrink: 0;
height: 25px;
width: 25px;
}
svg {
height: 10px;
margin-left: auto;
margin-right: $size-2;
width: 10px;
}
}
.dropdown {
left: 15px;
bottom: 45px;
min-width: 189px;
@include animation(0, 0.2s, fadeInUp);
li {
font-size: $fs14;
padding: $size-2 $size-4;
svg {
fill: $color-gray-20;
margin-right: $size-2;
height: 12px;
width: 12px;
}
&.separator {
border-top: 1px solid $color-gray-10;
}
}
}
}
.primary-badge {
border: 1px solid $color-primary;
border-radius: $br2;
font-size: $fs9 !important;
font-weight: $fw500;
color: $color-primary !important;
padding: 2px 4px;
}

View File

@ -1,605 +0,0 @@
.dashboard-invite-modal {
top: 72px;
right: 13px;
padding: 32px;
box-shadow: 0px 4px 8px rgba($color-black, 0.25);
border-radius: $br8;
width: 400px;
position: fixed;
z-index: 16;
&.hero {
top: 218px;
right: 35px;
}
form {
width: 100%;
}
.form-row {
display: flex;
justify-content: space-between;
margin: 4px 0px;
.label {
margin-bottom: 0;
display: flex;
align-items: center;
}
}
.custom-input {
width: 100%;
min-height: 116px;
max-height: 176px;
overflow-y: hidden;
input {
&.no-padding {
padding-top: 12px;
height: 50px;
}
min-height: 40px;
}
.selected-items {
gap: 8px;
padding: 8px;
max-height: 132px;
overflow-y: scroll;
.selected-item {
.around {
height: 24px;
display: flex;
align-items: center;
justify-content: flex-start;
width: fit-content;
.icon {
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
.custom-select {
width: 180px;
overflow: hidden;
justify-content: normal;
select {
height: auto;
}
}
.action-buttons {
display: flex;
margin-top: 16px;
input[type="submit"] {
margin-bottom: 0px;
}
}
.title {
color: $color-black;
font-weight: $fw700;
margin-bottom: 16px;
}
.hint {
font-size: $fs12;
&.hidden {
display: none;
}
}
svg {
width: 12px;
height: 12px;
fill: $color-gray-20;
}
.error,
.warning {
width: 100%;
display: flex;
.icon {
text-align: center;
padding: 5px;
svg {
fill: $color-white;
width: 20px;
height: 20px;
margin: 5px;
}
}
.text {
color: $color-black;
padding: 5px;
font-size: $fs12;
}
}
.error {
background-color: #ffd9e0;
.icon {
background-color: $color-danger;
}
}
.warning {
background-color: #ffeaca;
.icon {
background-color: $color-warning;
}
}
}
.dashboard-team-members,
.dashboard-team-invitations,
.dashboard-team-webhooks {
.empty-invitations {
height: 156px;
max-width: 1040px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
border: 1px dashed $color-gray-20;
margin-top: 16px;
}
.table-header {
user-select: none;
}
.table-row {
background-color: $color-white;
height: 63px;
&:not(:first-child) {
margin-top: 16px;
}
}
.table-field {
&.name {
width: 43%;
min-width: 300px;
display: flex;
.member-info {
display: flex;
flex-direction: column;
margin-left: 16px;
.member-name {
font-size: $fs16;
.you {
color: $color-gray-30;
margin-left: 5px;
}
}
.member-email {
color: $color-gray-30;
font-size: $fs12;
}
}
.member-image {
height: 32px;
width: 32px;
img {
border-radius: 50%;
}
}
}
&.roles {
flex-grow: 1;
cursor: default;
position: relative;
.rol-label {
user-select: none;
}
.rol-selector {
&.has-priv {
border: 1px solid $color-gray-20;
cursor: pointer;
}
min-width: 160px;
height: 32px;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: $br2;
padding: 3px 8px;
font-size: $fs14;
}
}
&.actions {
position: relative;
.actions-dropdown {
max-height: 30rem;
min-width: 180px;
}
}
&.status {
.status-badge {
color: $color-white;
border-radius: $br12;
min-width: 74px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
&.pending {
background-color: $color-warning;
}
&.expired {
background-color: $color-gray-20;
}
.status-label {
font-size: $fs12;
}
}
}
&.uri {
flex-grow: 1;
}
&.active {
min-width: 100px;
}
&.last-delivery {
display: flex;
justify-content: center;
width: 50px;
position: relative;
.success svg {
fill: $color-primary;
width: 16px;
height: 16px;
}
.failure svg {
fill: $color-warning;
width: 16px;
height: 16px;
}
.icon-container {
width: 16px;
height: 16px;
overflow-x: visible;
}
.icon {
padding: 0;
}
}
.tooltip {
display: none;
position: absolute;
top: -58px;
left: 50%;
transform: translate(-50%, 0);
text-align: center;
.label {
border-radius: $br3;
color: $color-white;
background-color: $color-black;
white-space: nowrap;
padding: 12px 20px;
}
.arrow-down {
margin: 0 auto;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-top: 8px solid $color-black;
}
}
.last-delivery-icon:hover {
.tooltip {
display: block;
}
}
}
.dropdown {
position: absolute;
max-height: 30rem;
overflow-y: auto;
background-color: $color-white;
border-radius: $br4;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
z-index: 12;
top: 30px;
left: -151px;
width: 155px;
hr {
margin: 0;
border-color: $color-gray-10;
}
li {
display: flex;
align-items: center;
color: $color-gray-60;
cursor: pointer;
font-size: $fs14;
height: 31px;
padding: 5px 16px;
&.title {
font-weight: $fw600;
cursor: default;
}
&:hover {
background-color: $color-primary-lighter;
}
}
}
}
.dashboard-team-settings {
.team-settings {
display: flex;
justify-content: center;
margin-top: 16px;
svg {
width: 20px;
height: 20px;
}
.horizontal-blocks {
display: flex;
max-width: 1010px;
justify-content: space-between;
width: 100%;
}
.block {
display: flex;
max-width: 324px;
width: 324px;
background-color: $color-white;
flex-direction: column;
padding: 12px;
.label {
font-size: $fs13;
color: $color-gray-30;
}
}
.info-block {
position: relative;
.name {
margin-top: 10px;
font-size: $fs24;
color: $color-black;
@include text-ellipsis;
margin-right: 90px;
}
.icon {
position: absolute;
padding: 15px;
width: 100px;
height: 100px;
right: 0px;
top: 0px;
img {
border-radius: 50%;
width: 70px;
height: 70px;
}
.update-overlay {
opacity: 0;
cursor: pointer;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
width: 71px;
height: 71px;
border-radius: 50%;
color: $color-white;
background: $color-primary-dark;
z-index: 14;
svg {
fill: $color-white;
}
}
&:hover {
.update-overlay {
opacity: 1;
width: 72px;
height: 72px;
top: 14px;
left: 14px;
}
}
}
}
.owner-block {
img {
width: 30px;
height: 30px;
border-radius: 50%;
}
svg {
width: 12px;
height: 12px;
fill: $color-black;
}
.owner {
margin-top: 5px;
display: flex;
align-items: center;
color: $color-black;
.icon {
margin-right: 12px;
}
}
.summary {
margin-top: 5px;
color: $color-black;
.icon {
padding: 0px 10px;
margin-right: 12px;
}
}
}
.stats-block {
svg {
fill: $color-black;
}
.projects,
.files {
margin-top: 7px;
display: flex;
align-items: center;
color: $color-black;
.icon {
display: flex;
align-items: center;
padding: 0px 2px;
margin-right: 14px;
}
}
}
}
}
.dashboard-team-webhooks {
display: flex;
flex-direction: column;
align-items: center;
.webhooks-hero-container {
max-width: 1000px;
width: 100%;
display: flex;
flex-direction: column;
.upload-button {
width: 100px;
}
.btn-secondary {
margin-left: 10px;
}
}
.webhooks-hero {
font-size: $fs14;
padding: $size-6;
background-color: $color-white;
margin-top: $size-6;
display: flex;
justify-content: space-between;
.banner {
background-color: unset;
display: flex;
.icon {
display: flex;
align-items: center;
padding-left: 0px;
padding-right: 10px;
svg {
fill: $color-info;
}
}
}
.desc {
h2 {
margin-bottom: $size-4;
color: $color-black;
}
width: 80%;
color: $color-gray-40;
p {
font-size: $fs16;
}
}
.btn-primary {
flex-shrink: 0;
}
}
.webhooks-empty {
text-align: center;
max-width: 1000px;
width: 100%;
padding: $size-6;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 1px dashed $color-gray-20;
color: $color-gray-40;
margin-top: 12px;
min-height: 136px;
}
}
.webhooks-modal {
.action-buttons {
gap: 10px;
.cancel-button {
border: 1px solid $color-gray-30;
background: $color-canvas;
border-radius: $br3;
padding: 0.5rem 1rem;
cursor: pointer;
margin-right: 8px;
&:hover {
background: $color-gray-20;
}
}
}
.input-checkbox label {
font-size: $fs14;
color: $color-black;
}
.explain {
font-size: $fs12;
color: $color-gray-40;
}
}

View File

@ -1,638 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.team-hero {
display: flex;
position: relative;
border: 2px solid $color-gray-10;
border-radius: $br8;
padding: 20px;
margin: 0 1rem 0 21px;
height: 154px;
.text {
flex-grow: 1;
padding-left: 20px;
.title {
font-size: $fs24;
font-weight: $fw700;
color: $color-black;
}
.info {
span {
color: $color-gray-30;
display: block;
}
padding-top: 10px;
}
}
.close {
position: absolute;
top: 20px;
right: 20px;
background-color: transparent;
border: none;
cursor: pointer;
svg {
transform: rotate(45deg);
width: 16px;
height: 16px;
}
}
.invite {
align-self: flex-end;
height: 40px;
font-family: "worksans", sans-serif;
width: 180px;
}
img {
width: 274px;
margin-bottom: -19px;
@media (max-width: 1200px) {
display: none;
width: 0;
}
}
}
.hero-projects {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 30px;
margin: 0 1rem 1rem 1.2rem;
.tutorial,
.walkthrough {
display: grid;
grid-template-columns: 1fr 1fr;
position: relative;
border: 2px solid $color-gray-10;
border-radius: $br8;
min-height: 211px;
.thumbnail {
border-top-left-radius: $br6;
border-bottom-left-radius: $br6;
padding: 30px;
display: block;
background-color: #e0e4e9;
}
.text {
padding: 30px;
.title {
color: $color-black;
font-size: $fs24;
font-weight: $fw700;
margin-bottom: 8px;
}
.info {
color: $color-gray-50;
margin-bottom: 20px;
font-size: $fs14;
}
}
.action {
font-family: "worksans", sans-serif;
width: 180px;
height: 40px;
}
.close {
position: absolute;
top: 0;
right: 0;
width: $size-5;
cursor: pointer;
display: flex;
margin: 20px;
justify-content: center;
align-items: center;
background-color: transparent;
border: none;
.icon {
svg {
fill: $color-gray-30;
height: 16px;
width: 16px;
transform: rotate(45deg);
&:hover {
fill: $color-primary;
}
}
}
}
@media (max-width: 1846px) {
grid-template-columns: 190px 1fr;
}
@media (max-width: 1526px) {
grid-template-columns: 1fr;
.img {
display: none;
width: 0;
}
}
}
.walkthrough {
.thumbnail {
background-image: url("/images/walkthrough-cover.png");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
}
.tutorial {
.thumbnail {
background-image: url("/images/hands-on-tutorial.png");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.loader {
display: flex;
svg#loader-pencil {
width: 31px;
}
}
}
}
.dashboard-container {
background-color: $color-dashboard;
flex: 1 0 0;
margin-right: $size-4;
overflow-y: auto;
width: 100%;
&.dashboard-projects {
user-select: none;
}
&.no-bg {
background-color: transparent;
}
&.dashboard-shared {
width: calc(100vw - 320px);
margin-right: 50px;
}
&.search {
margin-top: 10px;
}
}
.dashboard-project-row {
margin-bottom: $size-5;
position: relative;
.project {
align-items: center;
background: $color-white;
border-radius: $br3;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: $size-4;
padding: $size-2 $size-2 $size-2 $size-4;
width: 99%;
max-height: 40px;
gap: $size-2;
.project-name-wrapper {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 32px;
margin-left: $size-2;
}
.show-more {
align-items: center;
color: $color-gray-30;
display: flex;
font-size: $fs14;
justify-content: space-between;
cursor: pointer;
background-color: transparent;
border: none;
.placeholder-icon {
transform: rotate(-90deg);
margin-left: 10px;
svg {
height: 14px;
width: 14px;
fill: $color-gray-30;
}
}
&:hover {
color: $color-primary-dark;
svg {
fill: $color-primary-dark;
}
}
}
.btn-secondary {
border: none;
padding: $size-2;
}
h2 {
cursor: pointer;
font-size: $fs18;
line-height: $lh-088; // Original value was 1rem = 16px; 16px/18px = 88.88888% => $lh-088
font-weight: $fw600;
color: $color-black;
margin-right: $size-1;
}
.edit-wrapper {
margin-right: $size-4;
}
.info {
font-size: $fs14;
line-height: $lh-115; // Original value was 1rem = 16px; 16px/14px = 114.285714286% => $lh-115 (rounded)
font-weight: $fw400;
color: $color-gray-60;
margin-left: 0.75rem;
@media (max-width: 760px) {
display: none;
}
}
.project-actions {
display: flex;
opacity: 0;
margin-left: $size-6;
.btn-small {
height: 32px;
margin: 0 $size-2;
width: 32px;
}
}
.pin-icon {
cursor: pointer;
display: flex;
align-items: center;
margin-right: 14px;
background-color: transparent;
border: none;
svg {
width: 15px;
height: 15px;
fill: $color-gray-20;
}
&.active {
svg {
fill: $color-gray-50;
}
}
}
}
&:hover,
&:focus,
&:focus-within {
.project-actions {
opacity: 1;
}
}
.show-more {
align-items: center;
color: $color-gray-30;
display: flex;
font-size: $fs14;
justify-content: space-between;
cursor: pointer;
background-color: transparent;
border: none;
position: absolute;
top: 9px;
right: 53px;
.placeholder-icon {
transform: rotate(-90deg);
margin-left: 10px;
svg {
height: 14px;
width: 14px;
fill: $color-gray-30;
}
}
&:hover {
color: $color-primary-dark;
svg {
fill: $color-primary-dark;
}
}
}
}
.recent-files-row-title-info {
color: $color-gray-60;
line-height: $lh-115; // Original value was 1rem = 16px; 16px/14px = 114.285714286% => $lh-115
font-size: $fs14;
font-weight: $fw400;
@media (max-width: 880px) {
display: none;
}
}
.dashboard-table {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20px;
font-size: $fs16;
&.team-members {
margin-bottom: 52px;
}
&.invitations {
.table-row {
display: grid;
grid-template-columns: 43% 1fr 109px 12px;
}
}
.table-header {
display: grid;
grid-template-columns: 43% 1fr 109px 12px;
max-width: 1040px;
background-color: $color-white;
color: $color-gray-30;
width: 100%;
height: 40px;
padding: 0px 16px;
}
.table-rows {
display: flex;
flex-direction: column;
max-width: 1040px;
width: 100%;
margin-top: 16px;
color: $color-black;
}
.table-row {
display: flex;
width: 100%;
height: 45px;
align-items: center;
padding: 0px 16px;
}
.table-field {
display: flex;
align-items: center;
.icon {
padding-left: 10px;
cursor: pointer;
}
}
svg {
width: 10px;
height: 10px;
fill: $color-black;
}
}
.edit-wrapper {
border: 1px solid $color-gray-10;
border-radius: $br3;
display: flex;
padding-right: $size-5;
position: relative;
input.element-title {
border: 0;
height: 30px;
padding: 5px;
margin: 0;
width: 100%;
background-color: $color-white;
}
.close {
cursor: pointer;
position: absolute;
top: 1px;
right: 2px;
svg {
fill: $color-gray-30;
height: 15px;
transform: rotate(45deg) translateY(7px);
width: 15px;
margin: 0;
}
}
}
.import-file-btn {
align-items: center;
display: flex;
flex-direction: column;
height: 2rem;
justify-content: center;
overflow: hidden;
padding: 4px;
width: 2rem;
background: none;
border: 1px solid $color-gray-20;
border-radius: $br2;
cursor: pointer;
transition: all 0.4s;
margin-left: 1rem;
&:hover {
background: $color-primary;
}
svg {
width: 16px;
height: 16px;
}
}
.dashboard-templates-section {
position: absolute;
display: flex;
flex-direction: column;
justify-content: flex-end;
bottom: 0;
width: 100%;
height: 228px;
transition: bottom 300ms;
pointer-events: none;
&.collapsed {
bottom: -228px;
transition: bottom 300ms;
}
.title {
pointer-events: all;
width: fit-content;
top: -56px;
right: -28px;
text-align: right;
height: 56px;
position: absolute;
button {
border: none;
cursor: pointer;
height: 58px;
display: inline-flex;
align-items: center;
border-top: 2px solid #e4e4e4;
border-left: 2px solid #e4e4e4;
border-right: 2px solid #e4e4e4;
border-top-left-radius: $br10;
border-top-right-radius: $br10;
margin-right: 30px;
background-color: $color-white;
position: relative;
z-index: 1;
span {
display: inline-block;
vertical-align: middle;
line-height: $lh-normal;
font-size: $fs18;
font-weight: $fw600;
color: $color-black;
margin-left: 18px;
margin-right: 10px;
&.icon {
margin-left: 10px;
margin-right: 16px;
}
}
svg {
width: 12px;
height: 12px;
}
}
}
.button {
position: absolute;
top: 133px;
border: 2px solid #e0e4e9;
border-radius: 50%;
text-align: center;
width: 35px;
height: 35px;
cursor: pointer;
background-color: $color-white;
display: flex;
align-items: center;
justify-content: center;
pointer-events: all;
svg {
width: 12px;
height: 12px;
}
&.left {
left: 0;
margin-left: 43px;
}
&.right {
right: 0;
margin-right: 43px;
}
&:hover {
border: 2px solid $color-primary;
}
}
.content {
pointer-events: all;
background-color: $color-white;
width: 200%;
height: 229px;
border-top: 2px solid #e4e4e4;
border-left: 2px solid #e4e4e4;
margin-left: 5px;
position: absolute;
.card-container {
width: 275px;
margin-top: 20px;
display: inline-block;
text-align: center;
vertical-align: top;
background-color: transparent;
border: none;
padding: 0;
}
.template-card {
display: inline-block;
width: 255px;
font-size: $fs16;
color: #181a22;
cursor: pointer;
.img-container {
width: 100%;
height: 135px;
margin-bottom: 15px;
border-radius: $br5;
border: 2px solid #e0e4e9;
display: flex;
justify-content: center;
flex-direction: column;
}
.card-name {
padding: 0 5px;
display: flex;
justify-content: space-between;
height: 23px;
svg {
width: 16px;
height: 16px;
}
span {
font-weight: $fw500;
font-size: $fs14;
}
}
.template-link {
border: 2px solid transparent;
margin: 30px;
padding: 32px 0;
}
.template-link-title {
font-size: $fs14;
font-weight: $fw600;
color: $color-gray-60;
}
.template-link-text {
font-size: $fs12;
margin-top: $size-2;
color: $color-gray-50;
}
&:hover {
.img-container {
border: 2px solid $color-primary;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,243 +0,0 @@
.share-modal {
background: none;
display: block;
top: 50px;
left: calc(100vw - 500px);
.share-link-dialog {
width: 480px;
background-color: $color-white;
box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 20%);
.modal-content {
padding: 16px 32px;
&:first-child {
border-top: 0px;
padding: 0;
height: 50px;
display: flex;
justify-content: center;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
margin-left: 32px;
h2 {
font-size: $fs18;
color: $color-black;
}
.modal-close-button {
margin-right: 16px;
}
}
.share-link-section {
.custom-input {
display: flex;
flex-direction: row;
margin-bottom: 15px;
border: 1px solid $color-gray-20;
input {
padding: 0 0 0 15px;
border: none;
}
}
.hint-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
.hint {
font-size: $fs12;
color: $color-gray-40;
}
.confirm-dialog {
display: flex;
flex-direction: column;
background-color: unset;
.actions {
display: flex;
justify-content: flex-end;
gap: 16px;
}
.description {
font-size: $fs12;
margin-bottom: 16px;
color: $color-black;
}
.btn-primary,
.btn-secondary,
.btn-warning,
.btn-danger {
width: 126px;
margin-bottom: 0px;
&:not(:last-child) {
margin-right: 10px;
}
}
}
}
label {
font-size: $fs12;
color: $color-black;
}
.help-icon {
height: 40px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: relative;
right: 0;
top: 0;
background-color: $color-gray-10;
border-left: 1px solid $color-gray-20;
svg {
fill: $color-gray-30;
}
&:hover {
background-color: $color-primary;
svg {
fill: $color-gray-60;
}
}
}
input {
margin: 0;
}
}
&.ops-section {
.manage-permissions {
display: flex;
color: $color-primary-dark;
font-size: $fs12;
cursor: pointer;
.icon {
svg {
height: 16px;
width: 16px;
fill: $color-primary-dark;
}
}
.title {
margin-left: 8px;
}
}
.view-mode {
min-height: 34px;
.subtitle {
height: 32px;
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
.count-pages {
font-size: $fs12;
color: $color-gray-30;
}
}
.current-tag {
font-size: $fs12;
color: $color-gray-30;
}
label {
color: $color-black;
}
}
.access-mode,
.inspect-mode {
display: grid;
grid-template-columns: auto 1fr;
.items {
display: flex;
justify-content: flex-end;
align-items: center;
}
}
.view-mode,
.access-mode,
.inspect-mode {
margin: 8px 0;
.subtitle {
display: flex;
justify-content: flex-start;
align-items: center;
color: $color-black;
font-size: $fs16;
.icon {
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
svg {
height: 16px;
width: 16px;
}
}
}
.items {
.input-select {
background-image: url("/images/icons/arrow-down.svg");
margin: 0;
padding-right: 28px;
border: 1px solid $color-gray-10;
max-width: 227px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
> .input-radio {
display: flex;
user-select: none;
margin-top: 0;
margin-bottom: 0;
label {
display: flex;
align-items: center;
color: $color-black;
max-width: 115px;
&::before {
height: 16px;
width: 16px;
}
.hint {
margin-left: 5px;
color: $color-gray-30;
}
}
&.disabled {
label {
color: $color-gray-30;
}
}
}
}
}
.pages-selection {
border-top: 1px solid $color-gray-10;
border-bottom: 1px solid $color-gray-10;
padding-left: 20px;
max-height: 200px;
overflow-y: scroll;
user-select: none;
label {
color: $color-black;
}
}
}
}
}
}

View File

@ -1,139 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.history-debug-overlay {
background: $color-gray-50;
bottom: 0;
max-height: 500px;
overflow-y: auto;
position: absolute;
width: 500px;
z-index: 1000;
}
.history-toolbox {
display: flex;
flex-direction: column;
}
.history-toolbox-title {
color: $color-gray-10;
font-size: $fs14;
padding: 0.5rem;
}
.history-entry-empty {
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
.history-entry-empty-icon {
margin-bottom: 1rem;
svg {
width: 32px;
height: 32px;
fill: $color-gray-40;
}
}
.history-entry-empty-msg {
color: $color-gray-30;
font-size: $fs12;
}
}
.history-entries {
font-size: $fs12;
color: $color-gray-20;
fill: $color-gray-20;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
}
.history-entry {
border: 1px solid $color-gray-60;
border-radius: $br4;
margin: 0.5rem;
display: flex;
flex-direction: column;
padding: 0.5rem;
cursor: pointer;
transition: border 0.2s;
&.disabled {
opacity: 0.5;
}
&.current {
background-color: $color-gray-60;
}
&.hover {
border-color: $color-primary;
}
}
.history-entry-summary {
display: flex;
flex-direction: row;
align-items: center;
* {
display: flex;
}
}
.history-entry-summary-icon {
svg {
width: 16px;
height: 16px;
}
}
.history-entry-summary-text {
flex: 1;
margin: 0 0.5rem;
margin-top: 2px;
}
.history-entry-summary-button {
opacity: 0;
transition: transform 0.2s;
svg {
width: 12px;
height: 12px;
}
.show-detail &,
.hover & {
opacity: 1;
}
.show-detail & {
transform: rotate(90deg);
}
}
.history-entry-detail {
display: none;
.show-detail & {
display: block;
padding: 1rem 0 0.5rem 0;
}
.history-entry-details-list {
margin: 0;
li {
margin-bottom: 0.5rem;
}
}
}

View File

@ -9,7 +9,6 @@
(:require (:require
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,8 @@
hint hint
accept-label accept-label
accept-style] :as props}] accept-style] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
on-accept (or on-accept identity) (let [on-accept (or on-accept identity)
message (or message (tr "ds.alert-title")) message (or message (tr "ds.alert-title"))
accept-label (or accept-label (tr "ds.alert-ok")) accept-label (or accept-label (tr "ds.alert-ok"))
accept-style (or accept-style :danger) accept-style (or accept-style :danger)
@ -50,54 +49,26 @@
(on-accept props)))] (on-accept props)))]
(->> (events/listen js/document "keydown" on-keydown) (->> (events/listen js/document "keydown" on-keydown)
(partial events/unlistenByKey)))) (partial events/unlistenByKey))))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} title]
[:h2 {:class (stl/css :modal-title)} title] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click accept-fn} i/close-refactor]]
:on-click accept-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message "")) (when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message]) [:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message "")) (when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message]) [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint) (when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])] [:p {:class (stl/css :modal-hint)} hint])]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css-case :accept-btn true [:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger) :danger (= accept-style :danger)
:primary (= accept-style :primary)) :primary (= accept-style :primary))
:type "button" :type "button"
:value accept-label :value accept-label
:on-click accept-fn}]]]]] :on-click accept-fn}]]]]]))
[:div.modal-overlay
[:div.modal-container.alert-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 title]]
[:div.modal-close-button
{:on-click accept-fn} i/close]]
[:div.modal-content
(when (and (string? message) (not= message ""))
[:h3 message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 scd-message])
(when (string? hint)
[:p hint])]
[:div.modal-footer
[:div.action-buttons
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]])))

View File

@ -11,39 +11,45 @@
&.transparent { &.transparent {
background-color: transparent; background-color: transparent;
} }
.modal-container { }
@extend .modal-container-base; .modal-container {
.modal-header { @extend .modal-container-base;
margin-bottom: $s-24; }
.modal-title {
@include tabTitleTipography; .modal-header {
color: var(--modal-title-foreground-color); margin-bottom: $s-24;
} }
.modal-close-btn {
@extend .modal-close-btn-base; .modal-title {
} @include tabTitleTipography;
} color: var(--modal-title-foreground-color);
.modal-content { }
@include titleTipography;
margin-bottom: $s-24; .modal-close-btn {
.modal-hint { @extend .modal-close-btn-base;
@include titleTipography; }
}
} .modal-content {
.modal-footer { @include titleTipography;
.action-buttons { margin-bottom: $s-24;
@extend .modal-action-btns; }
.cancel-button {
@extend .modal-cancel-btn; .modal-hint {
} @include titleTipography;
.accept-btn { }
@extend .modal-accept-btn;
&.danger { .action-buttons {
@extend .modal-danger-btn; @extend .modal-action-btns;
} }
}
} .cancel-button {
} @extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
} }
} }

View File

@ -12,7 +12,6 @@
[app.main.ui.auth.recovery :refer [recovery-page]] [app.main.ui.auth.recovery :refer [recovery-page]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]] [app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-page register-success-page register-validate-page]] [app.main.ui.auth.register :refer [register-page register-success-page register-validate-page]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -20,102 +19,57 @@
(mf/defc terms-login (mf/defc terms-login
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
show-terms? (some? cf/terms-of-service-uri) show-terms? (some? cf/terms-of-service-uri)
show-privacy? (some? cf/privacy-policy-uri)] show-privacy? (some? cf/privacy-policy-uri)]
(if new-css-system (when show-all?
(when show-all? [:div {:class (stl/css :terms-login)}
[:div {:class (stl/css :terms-login)} (when show-terms?
(when show-terms? [:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
[:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
(when show-all? (when show-all?
[:span (tr "labels.and")]) [:span (tr "labels.and")])
(when show-privacy? (when show-privacy?
[:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])]) [:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])])))
(when show-all?
[:div.terms-login
(when show-terms?
[:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
(when show-all?
[:span (tr "labels.and")])
(when show-privacy?
[:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])]))))
(mf/defc auth (mf/defc auth
[{:keys [route] :as props}] [{:keys [route] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [section (get-in route [:data :name])
section (get-in route [:data :name])
params (:query-params route) params (:query-params route)
show-illustration? (contains? cf/flags :login-illustration)] show-illustration? (contains? cf/flags :login-illustration)]
(mf/use-effect (mf/use-effect
#(dom/set-html-title (tr "title.default"))) #(dom/set-html-title (tr "title.default")))
(if new-css-system [:main {:class (stl/css-case :auth-section true
[:main {:class (stl/css-case :auth-section true :no-illustration (not show-illustration?))}
:no-illustration (not show-illustration?))} (when show-illustration?
(when show-illustration? [:div {:class (stl/css :login-illustration)}
[:div {:class (stl/css :login-illustration)} i/login-illustration])
i/login-illustration])
[:section {:class (stl/css :auth-content)} [:section {:class (stl/css :auth-content)}
[:* [:*
[:a {:href "#/" :class (stl/css :logo-btn)}i/logo] [:a {:href "#/" :class (stl/css :logo-btn)} i/logo]
(case section (case section
:auth-register :auth-register
[:& register-page {:params params}] [:& register-page {:params params}]
:auth-register-validate :auth-register-validate
[:& register-validate-page {:params params}] [:& register-validate-page {:params params}]
:auth-register-success :auth-register-success
[:& register-success-page {:params params}] [:& register-success-page {:params params}]
:auth-login :auth-login
[:& login-page {:params params}] [:& login-page {:params params}]
:auth-recovery-request :auth-recovery-request
[:& recovery-request-page] [:& recovery-request-page]
:auth-recovery :auth-recovery
[:& recovery-page {:params params}])] [:& recovery-page {:params params}])]
(when (contains? #{:auth-login :auth-register} section) (when (contains? #{:auth-login :auth-register} section)
[:& terms-login])]] [:& terms-login])]]))
;; OLD
[:main.auth
[:section.auth-sidebar
[:a.logo {:href "#/"}
[:span {:aria-hidden true} i/logo]
[:span.hidden-name "Home"]]
[:span.tagline (tr "auth.sidebar-tagline")]]
[:section.auth-content
(case section
:auth-register
[:& register-page {:params params}]
:auth-register-validate
[:& register-validate-page {:params params}]
:auth-register-success
[:& register-success-page {:params params}]
:auth-login
[:& login-page {:params params}]
:auth-recovery-request
[:& recovery-request-page]
:auth-recovery
[:& recovery-page {:params params}])
[:& terms-login {}]]])))

View File

@ -18,7 +18,6 @@
[app.main.ui.components.button-link :as bl] [app.main.ui.components.button-link :as bl]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk] [app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.messages :as msgs] [app.main.ui.messages :as msgs]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -94,8 +93,7 @@
(mf/defc login-form (mf/defc login-form
[{:keys [params on-success-callback origin] :as props}] [{:keys [params on-success-callback origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [initial (mf/use-memo (mf/deps params) (constantly params))
initial (mf/use-memo (mf/deps params) (constantly params))
error (mf/use-state false) error (mf/use-state false)
form (fm/use-form :spec ::login-form form (fm/use-form :spec ::login-form
:validators [handle-error-messages] :validators [handle-error-messages]
@ -157,156 +155,86 @@
(mf/use-fn (mf/use-fn
#(st/emit! (rt/nav :auth-recovery-request)))] #(st/emit! (rt/nav :auth-recovery-request)))]
(if new-css-system [:*
[:* (when-let [message @error]
(when-let [message @error] [:& msgs/inline-banner
[:& msgs/inline-banner {:type :warning
{:type :warning :content message
:content message :on-close #(reset! error nil)
:on-close #(reset! error nil) :data-test "login-banner"
:data-test "login-banner" :role "alert"}])
:role "alert"}])
[:& fm/form {:on-submit on-submit :form form} [:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input [:& fm/input
{:name :email {:name :email
:type "email" :type "email"
:label (tr "auth.email") :label (tr "auth.email")
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input [:& fm/input
{:type "password" {:type "password"
:name :password :name :password
:label (tr "auth.password") :label (tr "auth.password")
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
(when (and (not= origin :viewer) (when (and (not= origin :viewer)
(or (contains? cf/flags :login) (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))) (contains? cf/flags :login-with-password)))
[:div {:class (stl/css :fields-row :forgot-password)} [:div {:class (stl/css :fields-row :forgot-password)}
[:& lk/link {:action on-recovery-request [:& lk/link {:action on-recovery-request
:data-test "forgot-password"} :data-test "forgot-password"}
(tr "auth.forgot-password")]]) (tr "auth.forgot-password")]])
[:div {:class (stl/css :buttons-stack)} [:div {:class (stl/css :buttons-stack)}
(when (or (contains? cf/flags :login) (when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)) (contains? cf/flags :login-with-password))
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.login-submit") {:label (tr "auth.login-submit")
:data-test "login-submit" :data-test "login-submit"
:class (stl/css :login-button)}]) :class (stl/css :login-button)}])
(when (contains? cf/flags :login-with-ldap) (when (contains? cf/flags :login-with-ldap)
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit") {:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]] :on-click on-submit-ldap}])]]]))
;; OLD
[:*
(when-let [message @error]
[:& msgs/inline-banner
{:type :warning
:content message
:on-close #(reset! error nil)
:data-test "login-banner"
:role "alert"}])
[:& fm/form {:on-submit on-submit :form form}
[:div.fields-row
[:& fm/input
{:name :email
:type "email"
:help-icon i/at
:label (tr "auth.email")
:class (stl/css :form-field)}]]
[:div.fields-row
[:& fm/input
{:type "password"
:name :password
:help-icon i/eye
:label (tr "auth.password")
:class (stl/css :form-field)}]]
[:div.buttons-stack
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:> fm/submit-button*
{:label (tr "auth.login-submit")
:data-test "login-submit"}])
(when (contains? cf/flags :login-with-ldap)
[:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]])))
(mf/defc login-buttons (mf/defc login-buttons
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
login-with-github (mf/use-fn (mf/deps params) #(login-with-oidc % :github params)) login-with-github (mf/use-fn (mf/deps params) #(login-with-oidc % :github params))
login-with-gitlab (mf/use-fn (mf/deps params) #(login-with-oidc % :gitlab params)) login-with-gitlab (mf/use-fn (mf/deps params) #(login-with-oidc % :gitlab params))
login-with-oidc (mf/use-fn (mf/deps params) #(login-with-oidc % :oidc params))] login-with-oidc (mf/use-fn (mf/deps params) #(login-with-oidc % :oidc params))]
(if new-css-system [:div {:class (stl/css :auth-buttons)}
[:div {:class (stl/css :auth-buttons)} (when (contains? cf/flags :login-with-google)
(when (contains? cf/flags :login-with-google) [:& bl/button-link {:on-click login-with-google
[:& bl/button-link {:on-click login-with-google :icon i/brand-google
:icon i/brand-google :label (tr "auth.login-with-google-submit")
:label (tr "auth.login-with-google-submit") :class (stl/css :login-btn :btn-google-auth)}])
:class (stl/css :login-btn :btn-google-auth)}])
(when (contains? cf/flags :login-with-github) (when (contains? cf/flags :login-with-github)
[:& bl/button-link {:on-click login-with-github [:& bl/button-link {:on-click login-with-github
:icon i/brand-github :icon i/brand-github
:label (tr "auth.login-with-github-submit") :label (tr "auth.login-with-github-submit")
:class (stl/css :login-btn :btn-github-auth)}]) :class (stl/css :login-btn :btn-github-auth)}])
(when (contains? cf/flags :login-with-gitlab) (when (contains? cf/flags :login-with-gitlab)
[:& bl/button-link {:on-click login-with-gitlab [:& bl/button-link {:on-click login-with-gitlab
:icon i/brand-gitlab :icon i/brand-gitlab
:label (tr "auth.login-with-gitlab-submit") :label (tr "auth.login-with-gitlab-submit")
:class (stl/css :login-btn :btn-gitlab-auth)}]) :class (stl/css :login-btn :btn-gitlab-auth)}])
(when (contains? cf/flags :login-with-oidc) (when (contains? cf/flags :login-with-oidc)
[:& bl/button-link {:on-click login-with-oidc [:& bl/button-link {:on-click login-with-oidc
:icon i/brand-openid :icon i/brand-openid
:label (tr "auth.login-with-oidc-submit") :label (tr "auth.login-with-oidc-submit")
:class (stl/css :login-btn :btn-oidc-auth)}])] :class (stl/css :login-btn :btn-oidc-auth)}])]))
[:div.auth-buttons
(when (contains? cf/flags :login-with-google)
[:& bl/button-link {:on-click login-with-google
:icon i/brand-google
:label (tr "auth.login-with-google-submit")
:class "btn-google-auth"}])
(when (contains? cf/flags :login-with-github)
[:& bl/button-link {:on-click login-with-github
:icon i/brand-github
:label (tr "auth.login-with-github-submit")
:class "btn-github-auth"}])
(when (contains? cf/flags :login-with-gitlab)
[:& bl/button-link {:on-click login-with-gitlab
:icon i/brand-gitlab
:label (tr "auth.login-with-gitlab-submit")
:class "btn-gitlab-auth"}])
(when (contains? cf/flags :login-with-oidc)
[:& bl/button-link {:on-click login-with-oidc
:icon i/brand-openid
:label (tr "auth.login-with-oidc-submit")
:class "btn-github-auth"}])])))
(mf/defc login-button-oidc (mf/defc login-button-oidc
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [login-oidc
login-oidc
(mf/use-fn (mf/use-fn
(mf/deps params) (mf/deps params)
(fn [event] (fn [event]
@ -317,69 +245,33 @@
(fn [event] (fn [event]
(when (k/enter? event) (when (k/enter? event)
(login-oidc event))))] (login-oidc event))))]
(if new-css-system (when (contains? cf/flags :login-with-oidc)
(when (contains? cf/flags :login-with-oidc) [:div {:class (stl/css :link-entry :link-oidc)}
[:div {:class (stl/css :link-entry :link-oidc)} [:a {:tab-index "0"
[:a {:tab-index "0" :on-key-down handle-key-down
:on-key-down handle-key-down :on-click login-oidc}
:on-click login-oidc} (tr "auth.login-with-oidc-submit")]])))
(tr "auth.login-with-oidc-submit")]])
;; OLD
(when (contains? cf/flags :login-with-oidc)
[:div.link-entry.link-oidc
[:a {:tab-index "0"
:on-key-down handle-key-down
:on-click login-oidc}
(tr "auth.login-with-oidc-submit")]]))))
(mf/defc login-methods (mf/defc login-methods
[{:keys [params on-success-callback origin] :as props}] [{:keys [params on-success-callback origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:*
(if new-css-system (when show-alt-login-buttons?
[:* [:*
(when show-alt-login-buttons? [:& login-buttons {:params params}]
[:*
[:& login-buttons {:params params}]
(when (or (contains? cf/flags :login) (when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password) (contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap)) (contains? cf/flags :login-with-ldap))
[:hr {:class (stl/css :separator)}])]) [:hr {:class (stl/css :separator)}])])
(when (or (contains? cf/flags :login) (when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password) (contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap)) (contains? cf/flags :login-with-ldap))
[:& login-form {:params params :on-success-callback on-success-callback :origin origin}])] [:& login-form {:params params :on-success-callback on-success-callback :origin origin}])])
;; OLD
[:*
(when show-alt-login-buttons?
[:*
[:span.separator
[:span.line]
[:span.text (tr "labels.continue-with")]
[:span.line]]
[:& login-buttons {:params params}]
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:span.separator
[:span.line]
[:span.text (tr "labels.or")]
[:span.line]])])
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:& login-form {:params params :on-success-callback on-success-callback}])])))
(mf/defc login-page (mf/defc login-page
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [go-register
go-register
(mf/use-fn (mf/use-fn
#(st/emit! (rt/nav :auth-register {} params))) #(st/emit! (rt/nav :auth-register {} params)))
@ -391,64 +283,33 @@
(mf/use-fn (mf/use-fn
#(st/emit! (du/create-demo-profile)))] #(st/emit! (du/create-demo-profile)))]
(if new-css-system [:div {:class (stl/css :auth-form)}
[:div {:class (stl/css :auth-form)} [:h1 {:class (stl/css :auth-title)
[:h1 {:class (stl/css :auth-title) :data-test "login-title"} (tr "auth.login-title")]
:data-test "login-title"} (tr "auth.login-title")]
[:hr {:class (stl/css :separator)}] [:hr {:class (stl/css :separator)}]
[:& login-methods {:params params}] [:& login-methods {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
(when (or (contains? cf/flags :login) (when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)) (contains? cf/flags :login-with-password))
[:div {:class (stl/css :link-entry :register)} [:div {:class (stl/css :link-entry :register)}
[:& lk/link {:action on-pass-recovery [:& lk/link {:action on-pass-recovery
:data-test "forgot-password"} :data-test "forgot-password"}
(tr "auth.forgot-password")]]) (tr "auth.forgot-password")]])
(when (contains? cf/flags :registration) (when (contains? cf/flags :registration)
[:div {:class (stl/css :link-entry :register)} [:div {:class (stl/css :link-entry :register)}
[:span (tr "auth.register") " "] [:span (tr "auth.register") " "]
[:& lk/link {:action go-register [:& lk/link {:action go-register
:data-test "register-submit"} :data-test "register-submit"}
(tr "auth.register-submit")]])] (tr "auth.register-submit")]])]
(when (contains? cf/flags :demo-users) (when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-account)} [:div {:class (stl/css :link-entry :demo-account)}
[:span (tr "auth.create-demo-profile") " "] [:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action on-create-demo-profile [:& lk/link {:action on-create-demo-profile
:data-test "demo-account-link"} :data-test "demo-account-link"}
(tr "auth.create-demo-account")]])] (tr "auth.create-demo-account")]])]))
;; OLD
[:div.generic-form.login-form
[:div.form-container
[:h1 {:data-test "login-title"} (tr "auth.login-title")]
[:& login-methods {:params params}]
[:div.links
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:div.link-entry
[:& lk/link {:action on-pass-recovery
:data-test "forgot-password"}
(tr "auth.forgot-password")]])
(when (contains? cf/flags :registration)
[:div.link-entry
[:span (tr "auth.register") " "]
[:& lk/link {:action go-register
:data-test "register-submit"}
(tr "auth.register-submit")]])]
(when (contains? cf/flags :demo-users)
[:div.links.demo
[:div.link-entry
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action on-create-demo-profile
:data-test "demo-account-link"}
(tr "auth.create-demo-account")]]])]])))

View File

@ -12,7 +12,6 @@
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -57,73 +56,41 @@
(mf/defc recovery-form (mf/defc recovery-form
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form :spec ::recovery-form
form (fm/use-form :spec ::recovery-form
:validators [password-equality :validators [password-equality
(fm/validate-not-empty :password-1 (tr "auth.password-not-empty")) (fm/validate-not-empty :password-1 (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))] (fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))]
:initial params)] :initial params)]
(if new-css-system [:& fm/form {:on-submit on-submit :form form}
[:& fm/form {:on-submit on-submit :form form} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input {:type "password"
[:& fm/input {:type "password" :name :password-1
:name :password-1 :show-success? true
:show-success? true :label (tr "auth.new-password")
:label (tr "auth.new-password") :class (stl/css :form-field)}]]
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:type "password" [:& fm/input {:type "password"
:name :password-2 :name :password-2
:show-success? true :show-success? true
:label (tr "auth.confirm-password") :label (tr "auth.confirm-password")
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.recovery-submit") {:label (tr "auth.recovery-submit")
:class (stl/css :submit-btn)}]] :class (stl/css :submit-btn)}]]))
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:type "password"
:name :password-1
:label (tr "auth.new-password")}]]
[:div.fields-row
[:& fm/input {:type "password"
:name :password-2
:label (tr "auth.confirm-password")}]]
[:> fm/submit-button*
{:label (tr "auth.recovery-submit")}]])))
;; --- Recovery Request Page ;; --- Recovery Request Page
(mf/defc recovery-page (mf/defc recovery-page
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :auth-form)}
(if new-css-system [:h1 {:class (stl/css :auth-title)} "Forgot your password?"]
[:div {:class (stl/css :auth-form)} [:div {:class (stl/css :auth-subtitle)} "Please enter your new password"]
[:h1 {:class (stl/css :auth-title)} "Forgot your password?"] [:hr {:class (stl/css :separator)}]
[:div {:class (stl/css :auth-subtitle)} "Please enter your new password"] [:& recovery-form {:params params}]
[:hr {:class (stl/css :separator)}]
[:& recovery-form {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)} [:div {:class (stl/css :link-entry)}
[:a {:on-click #(st/emit! (rt/nav :auth-login))} [:a {:on-click #(st/emit! (rt/nav :auth-login))}
(tr "profile.recovery.go-to-login")]]]] (tr "profile.recovery.go-to-login")]]]])
;; TODO
[:section.generic-form
[:div.form-container
[:h1 "Forgot your password?"]
[:div.subtitle "Please enter your new password"]
[:& recovery-form {:params params}]
[:div.links
[:div.link-entry
[:a {:on-click #(st/emit! (rt/nav :auth-login))}
(tr "profile.recovery.go-to-login")]]]]])))

View File

@ -14,8 +14,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk] [app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
@ -34,8 +32,7 @@
(mf/defc recovery-form (mf/defc recovery-form
[{:keys [on-success-callback] :as props}] [{:keys [on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form :spec ::recovery-request-form
form (fm/use-form :spec ::recovery-request-form
:validators [handle-error-messages] :validators [handle-error-messages]
:initial {}) :initial {})
submitted (mf/use-state false) submitted (mf/use-state false)
@ -77,62 +74,34 @@
(reset! form nil) (reset! form nil)
(st/emit! (du/request-profile-recovery params)))))] (st/emit! (du/request-profile-recovery params)))))]
(if new-css-system [:& fm/form {:on-submit on-submit
[:& fm/form {:on-submit on-submit :form form}
:form form} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input {:name :email
[:& fm/input {:name :email :label (tr "auth.email")
:label (tr "auth.email") :type "text"
:type "text" :class (stl/css :form-field)}]]
:class (stl/css :form-field)}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.recovery-request-submit") {:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit" :data-test "recovery-resquest-submit"
:class (stl/css :recover-btn)}]] :class (stl/css :recover-btn)}]]))
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:name :email
:label (tr "auth.email")
:help-icon i/at
:type "text"}]]
[:> fm/submit-button*
{:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit"}]])))
;; --- Recovery Request Page ;; --- Recovery Request Page
(mf/defc recovery-request-page (mf/defc recovery-request-page
[{:keys [params on-success-callback go-back-callback] :as props}] [{:keys [params on-success-callback go-back-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [default-go-back #(st/emit! (rt/nav :auth-login))
default-go-back #(st/emit! (rt/nav :auth-login))
go-back (or go-back-callback default-go-back)] go-back (or go-back-callback default-go-back)]
(if new-css-system [:div {:class (stl/css :auth-form)}
[:div {:class (stl/css :auth-form)} [:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")]
[:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")] [:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")] [:hr {:class (stl/css :separator)}]
[:hr {:class (stl/css :separator)}]
[:& recovery-form {:params params :on-success-callback on-success-callback}] [:& recovery-form {:params params :on-success-callback on-success-callback}]
[:div {:class (stl/css :link-entry)} [:div {:class (stl/css :link-entry)}
[:& lk/link {:action go-back [:& lk/link {:action go-back
:data-test "go-back-link"} :data-test "go-back-link"}
(tr "labels.go-back")]]] (tr "labels.go-back")]]]))
;; old
[:section.generic-form
[:div.form-container
[:h1 (tr "auth.recovery-request-title")]
[:div.subtitle (tr "auth.recovery-request-subtitle")]
[:& recovery-form {:params params :on-success-callback on-success-callback}]
[:div.links
[:div.link-entry
[:& lk/link {:action go-back
:data-test "go-back-link"}
(tr "labels.go-back")]]]]])))

View File

@ -17,7 +17,6 @@
[app.main.ui.auth.login :as login] [app.main.ui.auth.login :as login]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk] [app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.messages :as msgs] [app.main.ui.messages :as msgs]
[app.util.i18n :refer [tr tr-html]] [app.util.i18n :refer [tr tr-html]]
@ -88,8 +87,7 @@
(mf/defc register-form (mf/defc register-form
[{:keys [params on-success-callback] :as props}] [{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [initial (mf/use-memo (mf/deps params) (constantly params))
initial (mf/use-memo (mf/deps params) (constantly params))
form (fm/use-form :spec ::register-form form (fm/use-form :spec ::register-form
:validators [validate :validators [validate
(fm/validate-not-empty :password (tr "auth.password-not-empty"))] (fm/validate-not-empty :password (tr "auth.password-not-empty"))]
@ -114,133 +112,64 @@
(partial handle-prepare-register-error form))))))] (partial handle-prepare-register-error form))))))]
(if new-css-system [:& fm/form {:on-submit on-submit :form form}
[:& fm/form {:on-submit on-submit :form form} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input {:type "email"
[:& fm/input {:type "email" :name :email
:name :email :label (tr "auth.email")
:label (tr "auth.email") :data-test "email-input"
:data-test "email-input" :show-success? true
:show-success? true :class (stl/css :form-field)}]]
:class (stl/css :form-field)}]] [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input {:name :password
[:& fm/input {:name :password :hint (tr "auth.password-length-hint")
:hint (tr "auth.password-length-hint") :label (tr "auth.password")
:label (tr "auth.password") :show-success? true
:show-success? true :type "password"
:type "password" :class (stl/css :form-field)}]]
:class (stl/css :form-field)}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.register-submit") {:label (tr "auth.register-submit")
:disabled @submitted? :disabled @submitted?
:data-test "register-form-submit" :data-test "register-form-submit"
:class (stl/css :register-btn)}]] :class (stl/css :register-btn)}]]))
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:type "email"
:name :email
:help-icon i/at
:label (tr "auth.email")
:data-test "email-input"}]]
[:div.fields-row
[:& fm/input {:name :password
:hint (tr "auth.password-length-hint")
:label (tr "auth.password")
:type "password"}]]
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:data-test "register-form-submit"}]])))
(mf/defc register-methods (mf/defc register-methods
[{:keys [params on-success-callback] :as props}] [{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:*
(if new-css-system (when login/show-alt-login-buttons?
[:* [:*
(when login/show-alt-login-buttons? [:hr {:class (stl/css :separator)}]
[:* [:& login/login-buttons {:params params}]])
[:hr {:class (stl/css :separator)}] [:hr {:class (stl/css :separator)}]
[:& login/login-buttons {:params params}]]) [:& register-form {:params params :on-success-callback on-success-callback}]])
[:hr {:class (stl/css :separator)}]
[:& register-form {:params params :on-success-callback on-success-callback}]]
;; OLD
[:*
(when login/show-alt-login-buttons?
[:*
[:span.separator
[:span.line]
[:span.text (tr "labels.continue-with")]
[:span.line]]
[:& login/login-buttons {:params params}]
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-ldap))
[:span.separator
[:span.line]
[:span.text (tr "labels.or")]
[:span.line]])])
[:& register-form {:params params :on-success-callback on-success-callback}]])))
(mf/defc register-page (mf/defc register-page
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :auth-form)}
(if new-css-system [:h1 {:class (stl/css :auth-title)
[:div {:class (stl/css :auth-form)} :data-test "registration-title"} (tr "auth.register-title")]
[:h1 {:class (stl/css :auth-title) [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
:data-test "registration-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
(when (contains? cf/flags :demo-warning) (when (contains? cf/flags :demo-warning)
[:& demo-warning]) [:& demo-warning])
[:& register-methods {:params params}] [:& register-methods {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :account)} [:div {:class (stl/css :link-entry :account)}
[:span (tr "auth.already-have-account") " "] [:span (tr "auth.already-have-account") " "]
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params)) [:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
:data-test "login-here-link"} :data-test "login-here-link"}
(tr "auth.login-here")]] (tr "auth.login-here")]]
(when (contains? cf/flags :demo-users) (when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-users)} [:div {:class (stl/css :link-entry :demo-users)}
[:span (tr "auth.create-demo-profile") " "] [:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action #(st/emit! (du/create-demo-profile))} [:& lk/link {:action #(st/emit! (du/create-demo-profile))}
(tr "auth.create-demo-account")]])]] (tr "auth.create-demo-account")]])]])
;; OLD
[:div.form-container
[:h1 {:data-test "registration-title"} (tr "auth.register-title")]
[:div.subtitle (tr "auth.register-subtitle")]
(when (contains? cf/flags :demo-warning)
[:& demo-warning])
[:& register-methods {:params params}]
[:div.links
[:div.link-entry
[:span (tr "auth.already-have-account") " "]
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
:data-test "login-here-link"}
(tr "auth.login-here")]]
(when (contains? cf/flags :demo-users)
[:div.link-entry
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action #(st/emit! (du/create-demo-profile))}
(tr "auth.create-demo-account")]])]])))
;; --- PAGE: register validation ;; --- PAGE: register validation
@ -284,8 +213,7 @@
(mf/defc register-validate-form (mf/defc register-validate-form
[{:keys [params on-success-callback] :as props}] [{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form :spec ::register-validate-form
form (fm/use-form :spec ::register-validate-form
:validators [(fm/validate-not-empty :fullname (tr "auth.name.not-all-space")) :validators [(fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))
(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))] (fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))]
:initial params) :initial params)
@ -306,103 +234,55 @@
(rx/subs! on-success (rx/subs! on-success
(partial handle-register-error form))))))] (partial handle-register-error form))))))]
(if new-css-system [:& fm/form {:on-submit on-submit :form form}
[:& fm/form {:on-submit on-submit :form form} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input {:name :fullname
[:& fm/input {:name :fullname :label (tr "auth.fullname")
:label (tr "auth.fullname") :type "text"
:type "text" :show-success? true
:show-success? true :class (stl/css :form-field)}]]
:class (stl/css :form-field)}]]
(when (contains? cf/flags :terms-and-privacy-checkbox) (when (contains? cf/flags :terms-and-privacy-checkbox)
(let [terms-label (let [terms-label
(mf/html (mf/html
[:& tr-html [:& tr-html
{:tag-name "div" {:tag-name "div"
:label "auth.terms-privacy-agreement-md" :label "auth.terms-privacy-agreement-md"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])] :params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)} [:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class "check-primary"
:type "checkbox"
:label terms-label}]]))
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:class (stl/css :register-btn)}]]
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:name :fullname
:label (tr "auth.fullname")
:type "text"}]]
(when (contains? cf/flags :terms-and-privacy-checkbox)
[:div.fields-row.input-visible.accept-terms-and-privacy-wrapper
[:& fm/input {:name :accept-terms-and-privacy [:& fm/input {:name :accept-terms-and-privacy
:class "check-primary" :class "check-primary"
:type "checkbox"} :type "checkbox"
[:span :label terms-label}]]))
(tr "auth.terms-privacy-agreement")]]
[:div.auth-links
[:a {:href "https://penpot.app/terms" :target "_blank"} (tr "auth.terms-of-service")]
[:span ",\u00A0"]
[:a {:href "https://penpot.app/privacy" :target "_blank"} (tr "auth.privacy-policy")]]])
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.register-submit") {:label (tr "auth.register-submit")
:disabled @submitted?}]]))) :disabled @submitted?
:class (stl/css :register-btn)}]]))
(mf/defc register-validate-page (mf/defc register-validate-page
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :auth-form)}
(if new-css-system [:h1 {:class (stl/css :auth-title)
[:div {:class (stl/css :auth-form)} :data-test "register-title"} (tr "auth.register-title")]
[:h1 {:class (stl/css :auth-title) [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
:data-test "register-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
[:hr {:class (stl/css :separator)}] [:hr {:class (stl/css :separator)}]
[:& register-validate-form {:params params}] [:& register-validate-form {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :go-back)} [:div {:class (stl/css :link-entry :go-back)}
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))} [:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
(tr "labels.go-back")]]]] (tr "labels.go-back")]]]])
;; OLD
[:div.form-container
[:h1 {:data-test "register-title"} (tr "auth.register-title")]
[:div.subtitle (tr "auth.register-subtitle")]
[:& register-validate-form {:params params}]
[:div.links
[:div.link-entry
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
(tr "labels.go-back")]]]])))
(mf/defc register-success-page (mf/defc register-success-page
[{:keys [params] :as props}] [{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :auth-form :register-success)}
(if new-css-system [:div {:class (stl/css :notification-icon)} i/icon-verify]
[:div {:class (stl/css :auth-form :register-success)} [:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
[:div {:class (stl/css :notification-icon)} i/icon-verify] [:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")] [:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])
[:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]]
;; OLD
[:div.form-container
[:div.notification-icon i/icon-verify]
[:div.notification-text (tr "auth.verification-email-sent")]
[:div.notification-text-email (:email params "")]
[:div.notification-text (tr "auth.check-your-email")]])))

View File

@ -11,7 +11,6 @@
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.static :as static] [app.main.ui.static :as static]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -62,8 +61,7 @@
(mf/defc verify-token (mf/defc verify-token
[{:keys [route] :as props}] [{:keys [route] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [token (get-in route [:query-params :token])
token (get-in route [:query-params :token])
bad-token (mf/use-state false)] bad-token (mf/use-state false)]
(mf/with-effect [] (mf/with-effect []
@ -96,6 +94,5 @@
(if @bad-token (if @bad-token
[:> static/invalid-token {}] [:> static/invalid-token {}]
[:div {:class (stl/css-case :verify-token new-css-system [:div {:class (stl/css :verify-token)}
:global/verify-token (not new-css-system))}
i/loader-pencil]))) i/loader-pencil])))

View File

@ -18,7 +18,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -81,20 +80,18 @@
(set! (.-height (.-style node)) "0") (set! (.-height (.-style node)) "0")
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))) (set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px")))))
[:textarea [:textarea {:ref local-ref
{:ref local-ref :auto-focus autofocus?
:auto-focus autofocus? :on-key-down on-key-down
:on-key-down on-key-down :on-focus on-focus*
:on-focus on-focus* :on-blur on-blur
:on-blur on-blur :value value
:value value :placeholder placeholder
:placeholder placeholder :on-change on-change*}]))
:on-change on-change*}]))
(mf/defc reply-form (mf/defc reply-form
[{:keys [thread] :as props}] [{:keys [thread] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [show-buttons? (mf/use-state false)
show-buttons? (mf/use-state false)
content (mf/use-state "") content (mf/use-state "")
disabled? (or (fm/all-spaces? @content) disabled? (or (fm/all-spaces? @content)
@ -123,54 +120,32 @@
(fn [] (fn []
(st/emit! (dcm/add-comment thread @content)) (st/emit! (dcm/add-comment thread @content))
(on-cancel)))] (on-cancel)))]
(if new-css-system [:div {:class (stl/css :reply-form)}
[:div {:class (stl/css :reply-form)} [:& resizing-textarea {:value @content
[:& resizing-textarea {:value @content :placeholder "Reply"
:placeholder "Reply" :on-blur on-blur
:on-blur on-blur :on-focus on-focus
:on-focus on-focus :select-on-focus? false
:select-on-focus? false :on-ctrl-enter on-submit
:on-ctrl-enter on-submit :on-change on-change}]
:on-change on-change}] (when (or @show-buttons? (seq @content))
(when (or @show-buttons? (seq @content)) [:div {:class (stl/css :buttons-wrapper)}
[:div {:class (stl/css :buttons-wrapper)} [:input.btn-secondary
[:input.btn-secondary {:type "button"
{:type "button" :class (stl/css :cancel-btn)
:class (stl/css :cancel-btn) :value "Cancel"
:value "Cancel" :on-click on-cancel}]
:on-click on-cancel}] [:input
[:input {:type "button"
{:type "button" :class (stl/css-case :post-btn true
:class (stl/css-case :post-btn true :global/disabled disabled?)
:global/disabled disabled?) :value "Post"
:value "Post" :on-click on-submit
:on-click on-submit :disabled disabled?}]])]))
:disabled disabled?}]])]
[:div.reply-form
[:& resizing-textarea {:value @content
:placeholder "Reply"
:on-blur on-blur
:on-focus on-focus
:on-ctrl-enter on-submit
:on-change on-change}]
(when (or @show-buttons? (seq @content))
[:div.buttons
[:input.btn-primary
{:type "button"
:value "Post"
:on-click on-submit
:disabled disabled?}]
[:input.btn-secondary
{:type "button"
:value "Cancel"
:on-click on-cancel}]])])))
(mf/defc draft-thread (mf/defc draft-thread
[{:keys [draft zoom on-cancel on-submit position-modifier]}] [{:keys [draft zoom on-cancel on-submit position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [position (cond-> (:position draft)
position (cond-> (:position draft)
(some? position-modifier) (some? position-modifier)
(gpt/transform position-modifier)) (gpt/transform position-modifier))
content (:content draft) content (:content draft)
@ -201,73 +176,42 @@
(mf/deps draft) (mf/deps draft)
(partial on-submit draft))] (partial on-submit draft))]
[:*
[:div
{:class (stl/css :floating-thread-bubble)
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
"?"]
[:div {:class (stl/css :thread-content)
:style {:top (str (- pos-y 24) "px")
:left (str (+ pos-x 28) "px")}
:on-click dom/stop-propagation}
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:select-on-focus? false
:on-esc on-esc
:on-change on-change
:on-ctrl-enter on-submit}]
[:div {:class (stl/css :buttons-wrapper)}
(if new-css-system [:input {:on-click on-esc
[:* :class (stl/css :cancel-btn)
[:div :type "button"
{:class (stl/css :floating-thread-bubble) :value "Cancel"}]
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
"?"]
[:div {:class (stl/css :thread-content)
:style {:top (str (- pos-y 24) "px")
:left (str (+ pos-x 28) "px")}
:on-click dom/stop-propagation}
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:select-on-focus? false
:on-esc on-esc
:on-change on-change
:on-ctrl-enter on-submit}]
[:div {:class (stl/css :buttons-wrapper)}
[:input {:on-click on-esc [:input {:on-click on-submit
:class (stl/css :cancel-btn) :type "button"
:type "button" :value "Post"
:value "Cancel"}] :class (stl/css-case :post-btn true
:global/disabled disabled?)
[:input {:on-click on-submit :disabled disabled?}]]]]]))
:type "button"
:value "Post"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:disabled disabled?}]]]]]
[:*
[:div.thread-bubble
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
[:span "?"]]
[:div.thread-content
{:style {:top (str (- pos-y 14) "px")
:left (str (+ pos-x 14) "px")}
:on-click dom/stop-propagation}
[:div.reply-form
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:on-esc on-esc
:on-ctrl-enter on-submit
:on-change on-change}]
[:div.buttons
[:input.btn-primary
{:on-click on-submit
:type "button"
:value "Post"
:disabled disabled?}]
[:input.btn-secondary
{:on-click on-esc
:type "button"
:value "Cancel"}]]]]])))
(mf/defc edit-form (mf/defc edit-form
[{:keys [content on-submit on-cancel] :as props}] [{:keys [content on-submit on-cancel] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [content (mf/use-state content)
content (mf/use-state content)
on-change on-change
(mf/use-fn (mf/use-fn
@ -281,44 +225,28 @@
disabled? (or (fm/all-spaces? @content) disabled? (or (fm/all-spaces? @content)
(str/empty-or-nil? @content))] (str/empty-or-nil? @content))]
(if new-css-system [:div {:class (stl/css :edit-form)}
[:div {:class (stl/css :edit-form)} [:& resizing-textarea {:value @content
[:& resizing-textarea {:value @content :autofocus true
:autofocus true :select-on-focus true
:select-on-focus true :select-on-focus? false
:select-on-focus? false :on-ctrl-enter on-submit*
:on-ctrl-enter on-submit* :on-change on-change}]
:on-change on-change}] [:div {:class (stl/css :buttons-wrapper)}
[:div {:class (stl/css :buttons-wrapper)} [:input {:type "button"
[:input {:type "button" :value "Cancel"
:value "Cancel" :class (stl/css :cancel-btn)
:class (stl/css :cancel-btn) :on-click on-cancel}]
:on-click on-cancel}] [:input {:type "button"
[:input {:type "button" :class (stl/css-case :post-btn true
:class (stl/css-case :post-btn true :global/disabled disabled?)
:global/disabled disabled?) :value "Post"
:value "Post" :on-click on-submit*
:on-click on-submit* :disabled disabled?}]]]))
:disabled disabled?}]]]
[:div.reply-form.edit-form
[:& resizing-textarea {:value @content
:autofocus true
:select-on-focus true
:on-ctrl-enter on-submit*
:on-change on-change}]
[:div.buttons
[:input.btn-primary {:type "button"
:value "Post"
:on-click on-submit*
:disabled disabled?}]
[:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]]])))
(mf/defc comment-item (mf/defc comment-item
[{:keys [comment thread users origin] :as props}] [{:keys [comment thread users origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [owner (get users (:owner-id comment))
owner (get users (:owner-id comment))
profile (mf/deref refs/profile) profile (mf/deref refs/profile)
options (mf/use-state false) options (mf/use-state false)
edition? (mf/use-state false) edition? (mf/use-state false)
@ -382,82 +310,46 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))] (st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))]
(if new-css-system [:div {:class (stl/css :comment-container)}
[:div {:class (stl/css :comment-container)} [:div {:class (stl/css :comment)}
[:div {:class (stl/css :comment)} [:div {:class (stl/css :author)}
[:div {:class (stl/css :author)} [:div {:class (stl/css :avatar)}
[:div {:class (stl/css :avatar)} [:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:img {:src (cfg/resolve-profile-photo-url owner)}]] [:div {:class (stl/css :name)}
[:div {:class (stl/css :name)} [:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :fullname)} (:fullname owner)] [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
(when (some? thread) (when (some? thread)
[:div {:class (stl/css :options-resolve-wrapper) [:div {:class (stl/css :options-resolve-wrapper)
:on-click toggle-resolved} :on-click toggle-resolved}
[:span {:class (stl/css-case :options-resolve true [:span {:class (stl/css-case :options-resolve true
:global/checked (:is-resolved thread))} i/tick-refactor]]) :global/checked (:is-resolved thread))} i/tick-refactor]])
(when (= (:id profile) (:id owner)) (when (= (:id profile) (:id owner))
[:div {:class (stl/css :options) [:div {:class (stl/css :options)
:on-click on-toggle-options} :on-click on-toggle-options}
i/menu-refactor])] i/menu-refactor])]
[:div {:class (stl/css :content)} [:div {:class (stl/css :content)}
(if @edition? (if @edition?
[:& edit-form {:content (:content comment) [:& edit-form {:content (:content comment)
:on-submit on-submit :on-submit on-submit
:on-cancel on-cancel}] :on-cancel on-cancel}]
[:span {:class (stl/css :text)} (:content comment)])]] [:span {:class (stl/css :text)} (:content comment)])]]
[:& dropdown {:show @options [:& dropdown {:show @options
:on-close on-hide-options} :on-close on-hide-options}
[:ul {:class (stl/css :comment-options-dropdown)} [:ul {:class (stl/css :comment-options-dropdown)}
[:li {:class (stl/css :context-menu-option)
:on-click on-edit-clicked}
(tr "labels.edit")]
(if thread
[:li {:class (stl/css :context-menu-option) [:li {:class (stl/css :context-menu-option)
:on-click on-edit-clicked} :on-click on-delete-thread}
(tr "labels.edit")] (tr "labels.delete-comment-thread")]
(if thread [:li {:class (stl/css :context-menu-option)
[:li {:class (stl/css :context-menu-option) :on-click on-delete-comment}
:on-click on-delete-thread} (tr "labels.delete-comment")])]]]))
(tr "labels.delete-comment-thread")]
[:li {:class (stl/css :context-menu-option)
:on-click on-delete-comment}
(tr "labels.delete-comment")])]]]
[:div.comment-container
[:div.comment
[:div.author
[:div.avatar
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div.name
[:div.fullname (:fullname owner)]
[:div.timeago (dt/timeago (:modified-at comment))]]
(when (some? thread)
[:div.options-resolve {:on-click toggle-resolved}
(if (:is-resolved thread)
[:span i/checkbox-checked]
[:span i/checkbox-unchecked])])
(when (= (:id profile) (:id owner))
[:div.options
[:div.options-icon {:on-click on-toggle-options} i/actions]])]
[:div.content
(if @edition?
[:& edit-form {:content (:content comment)
:on-submit on-submit
:on-cancel on-cancel}]
[:span.text (:content comment)])]]
[:& dropdown {:show @options
:on-close on-hide-options}
[:ul.dropdown.comment-options-dropdown
[:li {:on-click on-edit-clicked} (tr "labels.edit")]
(if thread
[:li {:on-click on-delete-thread} (tr "labels.delete-comment-thread")]
[:li {:on-click on-delete-comment} (tr "labels.delete-comment")])]]])))
(defn make-comments-ref (defn make-comments-ref
[thread-id] [thread-id]
@ -466,8 +358,7 @@
(mf/defc thread-comments (mf/defc thread-comments
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [thread zoom users origin position-modifier]}] [{:keys [thread zoom users origin position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [ref (mf/use-ref)
ref (mf/use-ref)
thread-id (:id thread) thread-id (:id thread)
@ -477,12 +368,8 @@
(some? position-modifier) (some? position-modifier)
(gpt/transform position-modifier)) (gpt/transform position-modifier))
pos-x (if new-css-system pos-x (+ (* (:x pos) zoom) 24)
(+ (* (:x pos) zoom) 24) pos-y (- (* (:y pos) zoom) 28)
(+ (* (:x pos) zoom) 14))
pos-y (if new-css-system
(- (* (:y pos) zoom) 28)
(- (* (:y pos) zoom) 14))
comments-ref (mf/with-memo [thread-id] comments-ref (mf/with-memo [thread-id]
@ -504,46 +391,24 @@
(mf/with-layout-effect [thread-pos comments-map] (mf/with-layout-effect [thread-pos comments-map]
(when-let [node (mf/ref-val ref)] (when-let [node (mf/ref-val ref)]
(dom/scroll-into-view-if-needed! node))) (dom/scroll-into-view-if-needed! node)))
(if new-css-system (when (some? comment)
(when (some? comment) [:div {:class (stl/css :thread-content)
[:div {:class (stl/css :thread-content) :style {:top (str pos-y "px")
:style {:top (str pos-y "px") :left (str pos-x "px")}
:left (str pos-x "px")} :on-click dom/stop-propagation}
:on-click dom/stop-propagation}
[:div {:class (stl/css :comments)} [:div {:class (stl/css :comments)}
[:& comment-item {:comment comment [:& comment-item {:comment comment
:users users :users users
:thread thread :thread thread
:origin origin}] :origin origin}]
(for [item (rest comments)] (for [item (rest comments)]
[:* {:key (dm/str (:id item))} [:* {:key (dm/str (:id item))}
[:& comment-item {:comment item [:& comment-item {:comment item
:users users :users users
:origin origin}]]) :origin origin}]])
[:div {:ref ref}]] [:div {:ref ref}]]
[:& reply-form {:thread thread}]]) [:& reply-form {:thread thread}]])))
(when (some? comment)
[:div.thread-content
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
[:div.comments
[:& comment-item {:comment comment
:users users
:thread thread
:origin origin}]
(for [item (rest comments)]
[:* {:key (dm/str (:id item))}
[:hr]
[:& comment-item {:comment item
:users users
:origin origin}]])
[:div {:ref ref}]]
[:& reply-form {:thread thread}]]))))
(defn use-buble (defn use-buble
[zoom {:keys [position frame-id]}] [zoom {:keys [position frame-id]}]
@ -602,8 +467,7 @@
(mf/defc thread-bubble (mf/defc thread-bubble
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [thread zoom open? on-click origin position-modifier]}] [{:keys [thread zoom open? on-click origin position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [pos (cond-> (:position thread)
pos (cond-> (:position thread)
(some? position-modifier) (some? position-modifier)
(gpt/transform position-modifier)) (gpt/transform position-modifier))
@ -658,37 +522,22 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(when (= origin :viewer) (when (= origin :viewer)
(on-click thread))))] (on-click thread))))]
(if new-css-system [:div {:style {:top (str pos-y "px")
[:div {:style {:top (str pos-y "px") :left (str pos-x "px")}
:left (str pos-x "px")} :on-pointer-down on-pointer-down*
:on-pointer-down on-pointer-down* :on-pointer-up on-pointer-up*
:on-pointer-up on-pointer-up* :on-pointer-move on-pointer-move*
:on-pointer-move on-pointer-move* :on-click on-click*
:on-click on-click* :on-lost-pointer-capture on-lost-pointer-capture
:on-lost-pointer-capture on-lost-pointer-capture :class (stl/css-case
:class (stl/css-case :floating-thread-bubble true
:floating-thread-bubble true :resolved (:is-resolved thread)
:resolved (:is-resolved thread) :unread (pos? (:count-unread-comments thread)))}
:unread (pos? (:count-unread-comments thread)))} [:span (:seqn thread)]]))
[:span (:seqn thread)]]
[:div.thread-bubble
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-pointer-down on-pointer-down*
:on-pointer-up on-pointer-up*
:on-pointer-move on-pointer-move*
:on-click on-click*
:on-lost-pointer-capture on-lost-pointer-capture
:class (dom/classnames
:resolved (:is-resolved thread)
:unread (pos? (:count-unread-comments thread)))}
[:span (:seqn thread)]])))
(mf/defc comment-thread (mf/defc comment-thread
[{:keys [item users on-click]}] [{:keys [item users on-click]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [owner (get users (:owner-id item))
owner (get users (:owner-id item))
on-click* on-click*
(mf/use-fn (mf/use-fn
(mf/deps item) (mf/deps item)
@ -698,99 +547,50 @@
(when (fn? on-click) (when (fn? on-click)
(on-click item))))] (on-click item))))]
(if new-css-system [:div {:class (stl/css :comment)
[:div {:class (stl/css :comment) :on-click on-click*}
:on-click on-click*} [:div {:class (stl/css :author)}
[:div {:class (stl/css :author)} [:div {:class (stl/css-case :thread-bubble true
[:div {:class (stl/css-case :thread-bubble true :resolved (:is-resolved item)
:resolved (:is-resolved item) :unread (pos? (:count-unread-comments item)))}
:unread (pos? (:count-unread-comments item)))} (:seqn item)]
(:seqn item)] [:div {:class (stl/css :avatar)}
[:div {:class (stl/css :avatar)} [:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:img {:src (cfg/resolve-profile-photo-url owner)}]] [:div {:class (stl/css :name)}
[:div {:class (stl/css :name)} [:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :fullname)} (:fullname owner)] [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]] [:div {:class (stl/css :content)}
[:div {:class (stl/css :content)} (:content item)]
(:content item)] [:div {:class (stl/css :replies)}
[:div {:class (stl/css :replies)} (let [unread (:count-unread-comments item ::none)
(let [unread (:count-unread-comments item ::none) total (:count-comments item 1)]
total (:count-comments item 1)] [:*
[:* (when (> total 1)
(when (> total 1) (if (= total 2)
(if (= total 2) [:span {:class (stl/css :total-replies)} "1 reply"]
[:span {:class (stl/css :total-replies)} "1 reply"] [:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
[:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
(when (and (> total 1) (> unread 0)) (when (and (> total 1) (> unread 0))
(if (= unread 1) (if (= unread 1)
[:span {:class (stl/css :new-replies)} "1 new reply"] [:span {:class (stl/css :new-replies)} "1 new reply"]
[:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]] [:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]))
[:div.comment {:on-click on-click*}
[:div.author
[:div.thread-bubble
{:class (dom/classnames
:resolved (:is-resolved item)
:unread (pos? (:count-unread-comments item)))}
(:seqn item)]
[:div.avatar
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div.name
[:div.fullname (:fullname owner) ", "]
[:div.timeago (dt/timeago (:modified-at item))]]]
[:div.content
[:span.text (:content item)]]
[:div.content.replies
(let [unread (:count-unread-comments item ::none)
total (:count-comments item 1)]
[:*
(when (> total 1)
(if (= total 2)
[:span.total-replies "1 reply"]
[:span.total-replies (str (dec total) " replies")]))
(when (and (> total 1) (> unread 0))
(if (= unread 1)
[:span.new-replies "1 new reply"]
[:span.new-replies (str unread " new replies")]))])]])))
(mf/defc comment-thread-group (mf/defc comment-thread-group
[{:keys [group users on-thread-click]}] [{:keys [group users on-thread-click]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :thread-group)}
(if new-css-system (if (:file-name group)
[:div {:class (stl/css :thread-group)} [:div {:class (stl/css :section-title)}
(if (:file-name group) [:span {:class (stl/css :file-name)} (:file-name group) ", "]
[:div {:class (stl/css :section-title)} [:span {:class (stl/css :page-name)} (:page-name group)]]
[:span {:class (stl/css :file-name)} (:file-name group) ", "]
[:span {:class (stl/css :page-name)} (:page-name group)]]
[:div {:class (stl/css :section-title)} [:div {:class (stl/css :section-title)}
[:span {:class (stl/css :icon)} i/document-refactor] [:span {:class (stl/css :icon)} i/document-refactor]
[:span {:class (stl/css :page-name)} (:page-name group)]]) [:span {:class (stl/css :page-name)} (:page-name group)]])
[:div {:class (stl/css :threads)} [:div {:class (stl/css :threads)}
(for [item (:items group)] (for [item (:items group)]
[:& comment-thread [:& comment-thread
{:item item {:item item
:on-click on-thread-click :on-click on-thread-click
:users users :users users
:key (:id item)}])]] :key (:id item)}])]])
[:div.thread-group
(if (:file-name group)
[:div.section-title
[:span.label.filename (:file-name group) ", "]
[:span.label (:page-name group)]]
[:div.section-title
[:span.icon i/file-html]
[:span.label (:page-name group)]])
[:div.threads
(for [item (:items group)]
[:& comment-thread
{:item item
:on-click on-thread-click
:users users
:key (:id item)}])]])))

View File

@ -13,96 +13,106 @@
border-radius: $br-8; border-radius: $br-8;
padding: $s-8 $s-16; padding: $s-8 $s-16;
.section-title {
@include titleTipography;
height: $s-32;
display: flex;
align-items: center;
margin-bottom: $s-8;
.file-name {
color: var(--comment-subtitle-color);
}
.page-name {
color: var(--comment-subtitle-color);
}
.icon {
display: flex;
align-items: center;
padding: 0 $s-6 0 $s-4;
width: $s-24;
height: $s-32;
margin-left: $s-6;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
}
.threads {
display: flex;
flex-direction: column;
gap: $s-24;
}
&:hover { &:hover {
background: $db-primary; background: $db-primary;
} }
} }
.section-title {
@include titleTipography;
height: $s-32;
display: flex;
align-items: center;
margin-bottom: $s-8;
}
.file-name {
color: var(--comment-subtitle-color);
}
.page-name {
color: var(--comment-subtitle-color);
}
.icon {
display: flex;
align-items: center;
padding: 0 $s-6 0 $s-4;
width: $s-24;
height: $s-32;
margin-left: $s-6;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
.threads {
display: flex;
flex-direction: column;
gap: $s-24;
}
// Comment-thread // Comment-thread
.comment { .comment {
@include titleTipography; @include titleTipography;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: $s-12; gap: $s-12;
.author { }
display: flex;
gap: $s-8; .author {
.thread-bubble { display: flex;
@extend .comment-bubbles; gap: $s-8;
&.resolved { }
@extend .resolved-comment-bubble;
} .thread-bubble {
&.unread { @extend .comment-bubbles;
@extend .unread-comment-bubble; &.resolved {
} @extend .resolved-comment-bubble;
}
.avatar {
height: $s-32;
width: $s-32;
border-radius: $br-circle;
img {
border-radius: $br-circle;
}
}
.name {
flex-grow: 1;
.fullname {
@include textEllipsis;
color: var(--comment-title-color);
}
.timeago {
@include textEllipsis;
color: var(--comment-subtitle-color);
}
}
} }
.content { &.unread {
@include titleTipography; @extend .unread-comment-bubble;
color: var(--color-foreground-primary);
}
.replies {
display: flex;
gap: $s-8;
.total-replies {
color: var(--color-foreground-secondary);
}
.new-replies {
color: var(--color-accent-primary);
}
} }
} }
.avatar {
height: $s-32;
width: $s-32;
border-radius: $br-circle;
img {
border-radius: $br-circle;
}
}
.name {
flex-grow: 1;
.fullname {
@include textEllipsis;
color: var(--comment-title-color);
}
.timeago {
@include textEllipsis;
color: var(--comment-subtitle-color);
}
}
.content {
@include titleTipography;
color: var(--color-foreground-primary);
}
.replies {
display: flex;
gap: $s-8;
}
.total-replies {
color: var(--color-foreground-secondary);
}
.new-replies {
color: var(--color-accent-primary);
}
// Thread-bubble // Thread-bubble
.floating-thread-bubble { .floating-thread-bubble {

View File

@ -8,7 +8,6 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.ui.context :as ctx]
[cuerdas.core :as str] [cuerdas.core :as str]
[promesa.core :as p] [promesa.core :as p]
[rumext.v2 :as mf] [rumext.v2 :as mf]
@ -20,8 +19,7 @@
(mf/defc code-block (mf/defc code-block
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [code type]}] [{:keys [code type]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [block-ref (mf/use-ref)
block-ref (mf/use-ref)
code (str/trim code)] code (str/trim code)]
(mf/with-effect [code type] (mf/with-effect [code type]
@ -29,7 +27,5 @@
(p/let [highlight-fn (lazy/load highlight-fn)] (p/let [highlight-fn (lazy/load highlight-fn)]
(highlight-fn node)))) (highlight-fn node))))
(if new-css-system [:pre {:class (dm/str type " " (stl/css :code-display)) :ref block-ref} code]))
[:pre {:class (dm/str type " " (stl/css :code-display)) :ref block-ref} code]
[:pre {:class (dm/str type " " "code-display") :ref block-ref} code])))

View File

@ -11,7 +11,6 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.components.dropdown :refer [dropdown']] [app.main.ui.components.dropdown :refer [dropdown']]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -68,7 +67,6 @@
min-width? (gobj/get props "min-width?" false) min-width? (gobj/get props "min-width?" false)
origin (gobj/get props "origin") origin (gobj/get props "origin")
route (mf/deref refs/route) route (mf/deref refs/route)
new-css-system (mf/use-ctx ctx/new-css-system)
in-dashboard? (= :dashboard-projects (:name (:data route))) in-dashboard? (= :dashboard-projects (:name (:data route)))
local (mf/use-state {:offset-y 0 local (mf/use-state {:offset-y 0
:offset-x 0 :offset-x 0
@ -191,149 +189,79 @@
(tm/schedule-on-idle (tm/schedule-on-idle
#(dom/focus! (dom/get-element (first ids))))) #(dom/focus! (dom/get-element (first ids)))))
(if new-css-system (when (and open? (some? (:levels @local)))
(when (and open? (some? (:levels @local))) [:> dropdown' props
[:> dropdown' props (let [level (-> @local :levels peek)
(let [level (-> @local :levels peek) original-options (:options level)
original-options (:options level) parent-original (:parent-option level)]
parent-original (:parent-option level)] [:div {:class (stl/css-case :is-selectable is-selectable
[:div {:class (stl/css-case :is-selectable is-selectable :context-menu true
:context-menu true :is-open open?
:is-open open? :fixed fixed?)
:fixed fixed?) :style {:top (+ top (:offset-y @local))
:style {:top (+ top (:offset-y @local)) :left (+ left (:offset-x @local))}
:left (+ left (:offset-x @local))} :on-key-down (on-key-down original-options parent-original)}
:on-key-down (on-key-down original-options parent-original)} (let [level (-> @local :levels peek)]
(let [level (-> @local :levels peek)] [:ul {:class (stl/css-case :min-width min-width?
[:ul {:class (stl/css-case :min-width min-width? :context-menu-items true)
:context-menu-items true) :role "menu"
:role "menu" :ref check-menu-offscreen}
:ref check-menu-offscreen} (when-let [parent-option (:parent-option level)]
(when-let [parent-option (:parent-option level)] [:*
[:* [:& context-menu-a11y-item
[:& context-menu-a11y-item {:id "go-back-sub-option"
{:id "go-back-sub-option" :class (stl/css :context-menu-item)
:class (stl/css :context-menu-item) :tab-index "0"
:tab-index "0" :on-key-down (fn [event]
:on-key-down (fn [event] (dom/prevent-default event))}
(dom/prevent-default event))} [:button {:class (stl/css :context-menu-action :submenu-back)
[:button {:class (stl/css :context-menu-action :submenu-back) :data-no-close true
:on-click exit-submenu}
[:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor]
parent-option]]
[:li {:class (stl/css :separator)}]])
(for [[index option] (d/enumerate (:options level))]
(let [option-name (:option-name option)
id (:id option)
sub-options (:sub-options option)
option-handler (:option-handler option)
data-test (:data-test option)]
(when option-name
(if (= option-name :separator)
[:li {:key (dm/str "context-item-" index)
:class (stl/css :separator)}]
[:& context-menu-a11y-item
{:id id
:key id
:class (stl/css-case
:is-selected (and selected (= option-name selected))
:selected (and selected (= data-test selected))
:context-menu-item true)
:key-index (dm/str "context-item-" index)
:tab-index "0"
:on-key-down (fn [event]
(dom/prevent-default event))}
(if-not sub-options
[:a {:class (stl/css :context-menu-action)
:on-click #(do (dom/stop-propagation %)
(on-close)
(option-handler %))
:data-test data-test}
(if (and in-dashboard? (= option-name "Default"))
(tr "dashboard.default-team-name")
option-name)
(when (and selected (= data-test selected))
[:span {:class (stl/css :selected-icon)} i/tick-refactor])]
[:a {:class (stl/css :context-menu-action :submenu)
:data-no-close true :data-no-close true
:on-click exit-submenu} :on-click (enter-submenu option-name sub-options)
[:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor] :data-test data-test}
parent-option]] option-name
[:span {:class (stl/css :submenu-icon)} i/arrow-refactor]])]))))])])])))
[:li {:class (stl/css :separator)}]])
(for [[index option] (d/enumerate (:options level))]
(let [option-name (:option-name option)
id (:id option)
sub-options (:sub-options option)
option-handler (:option-handler option)
data-test (:data-test option)]
(when option-name
(if (= option-name :separator)
[:li {:key (dm/str "context-item-" index)
:class (stl/css :separator)}]
[:& context-menu-a11y-item
{:id id
:key id
:class (stl/css-case
:is-selected (and selected (= option-name selected))
:selected (and selected (= data-test selected))
:context-menu-item true)
:key-index (dm/str "context-item-" index)
:tab-index "0"
:on-key-down (fn [event]
(dom/prevent-default event))}
(if-not sub-options
[:a {:class (stl/css :context-menu-action)
:on-click #(do (dom/stop-propagation %)
(on-close)
(option-handler %))
:data-test data-test}
(if (and in-dashboard? (= option-name "Default"))
(tr "dashboard.default-team-name")
option-name)
(when (and selected (= data-test selected))
[:span {:class (stl/css :selected-icon)} i/tick-refactor])]
[:a {:class (stl/css :context-menu-action :submenu)
:data-no-close true
:on-click (enter-submenu option-name sub-options)
:data-test data-test}
option-name
[:span {:class (stl/css :submenu-icon)} i/arrow-refactor]])]))))])])])
;; OLD
(when (and open? (some? (:levels @local)))
[:> dropdown' props
(let [level (-> @local :levels peek)
original-options (:options level)
parent-original (:parent-option level)]
[:div {:class (dom/classnames :is-selectable is-selectable
:context-menu true
:is-open open?
:fixed fixed?)
:style {:top (+ top (:offset-y @local))
:left (+ left (:offset-x @local))}
:on-key-down (on-key-down original-options parent-original)}
(let [level (-> @local :levels peek)]
[:ul {:class (dom/classnames :min-width min-width?
:context-menu-items true)
:role "menu"
:ref check-menu-offscreen}
(when-let [parent-option (:parent-option level)]
[:*
[:& context-menu-a11y-item
{:id "go-back-sub-option"
:tab-index "0"
:on-key-down (fn [event]
(dom/prevent-default event))}
[:div {:class (dom/classnames :context-menu-action true
:submenu-back true)
:data-no-close true
:on-click exit-submenu}
[:span i/arrow-slide]
parent-option]]
[:li.separator]])
(for [[index option] (d/enumerate (:options level))]
(let [option-name (:option-name option)
id (:id option)
sub-options (:sub-options option)
option-handler (:option-handler option)
data-test (:data-test option)]
(when option-name
(if (= option-name :separator)
[:li.separator {:key (dm/str "context-item-" index)}]
[:& context-menu-a11y-item
{:id id
:key id
:class (dom/classnames :is-selected (and selected (= option-name selected)))
:key-index (dm/str "context-item-" index)
:tab-index "0"
:on-key-down (fn [event]
(dom/prevent-default event))}
(if-not sub-options
[:a {:class (dom/classnames :context-menu-action true)
:on-click #(do (dom/stop-propagation %)
(on-close)
(option-handler %))
:data-test data-test}
(if (and in-dashboard? (= option-name "Default"))
(tr "dashboard.default-team-name")
option-name)]
[:a.context-menu-action.submenu
{:data-no-close true
:on-click (enter-submenu option-name sub-options)
:data-test data-test}
option-name
[:span i/arrow-slide]])]))))])])]))))
(mf/defc context-menu-a11y (mf/defc context-menu-a11y
{::mf/wrap-props false} {::mf/wrap-props false}

View File

@ -30,15 +30,14 @@
(when label-text (when label-text
[:label {:for input-id :class-name label-class} label-text]) [:label {:for input-id :class-name label-class} label-text])
[:input [:input {:style {:display "none"
{:style {:display "none" :width 0}
:width 0} :id input-id
:id input-id :multiple multi
:multiple multi :accept accept
:accept accept :type "file"
:type "file" :ref input-ref
:ref input-ref :on-change on-files-selected
:on-change on-files-selected :data-test data-test
:data-test data-test :aria-label "uploader"}]]))
:aria-label "uploader"}]]))

View File

@ -386,21 +386,19 @@
(mf/defc submit-button* (mf/defc submit-button*
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (or (unchecked-get props "form")
form (or (unchecked-get props "form")
(mf/use-ctx form-ctx)) (mf/use-ctx form-ctx))
label (unchecked-get props "label") label (unchecked-get props "label")
on-click (unchecked-get props "onClick") on-click (unchecked-get props "onClick")
children (unchecked-get props "children") children (unchecked-get props "children")
class (d/nilv (unchecked-get props "className") "btn-primary btn-large") class (unchecked-get props "className")
name (d/nilv (unchecked-get props "name") "submit") name (d/nilv (unchecked-get props "name") "submit")
disabled? (or (and (some? form) (not (:valid @form))) disabled? (or (and (some? form) (not (:valid @form)))
(true? (unchecked-get props "disabled"))) (true? (unchecked-get props "disabled")))
klass (dm/str class " " (if disabled? "btn-disabled" ""))
new-klass (dm/str class " " (if disabled? (stl/css :btn-disabled) "")) new-klass (dm/str class " " (if disabled? (stl/css :btn-disabled) ""))
on-key-down on-key-down
@ -416,7 +414,7 @@
(obj/set! "onKeyDown" on-key-down) (obj/set! "onKeyDown" on-key-down)
(obj/set! "name" name) (obj/set! "name" name)
(obj/set! "label" mf/undefined) (obj/set! "label" mf/undefined)
(obj/set! "className" (if new-css-system new-klass klass)) (obj/set! "className" new-klass)
(obj/set! "type" "submit"))] (obj/set! "type" "submit"))]
[:> "button" props [:> "button" props

View File

@ -9,7 +9,6 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
@ -19,9 +18,8 @@
(mf/defc tab-element (mf/defc tab-element
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
(let [children (unchecked-get props "children") (let [children (unchecked-get props "children")]
new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :tab-element)}
[:div {:class (stl/css new-css-system :tab-element)}
children])) children]))
(mf/defc tab-container (mf/defc tab-container

View File

@ -9,7 +9,6 @@
(:require (:require
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr t]] [app.util.i18n :as i18n :refer [tr t]]
@ -31,8 +30,7 @@
cancel-label cancel-label
accept-label accept-label
accept-style] :as props}] accept-style] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [locale (mf/deref i18n/locale)
locale (mf/deref i18n/locale)
on-accept (or on-accept identity) on-accept (or on-accept identity)
on-cancel (or on-cancel identity) on-cancel (or on-cancel identity)
@ -67,87 +65,45 @@
(partial events/unlistenByKey)))) (partial events/unlistenByKey))))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} title]
[:h2 {:class (stl/css :modal-title)} title] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click cancel-fn} i/close-refactor]]
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message "")) (when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message]) [:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message "")) (when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message]) [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint) (when (string? hint)
[:p {:class (stl/css :modal-hint)} hint]) [:p {:class (stl/css :modal-hint)} hint])
(when (> (count items) 0) (when (> (count items) 0)
[:* [:*
[:p {:class (stl/css :modal-subtitle)} [:p {:class (stl/css :modal-subtitle)}
(tr "ds.component-subtitle")] (tr "ds.component-subtitle")]
[:ul {:class (stl/css :component-list)} [:ul {:class (stl/css :component-list)}
(for [item items] (for [item items]
[:li {:class (stl/css :modal-item-element)} [:li {:class (stl/css :modal-item-element)}
[:span {:class (stl/css :modal-component-icon)} [:span {:class (stl/css :modal-component-icon)}
i/component-refactor] i/component-refactor]
[:span {:class (stl/css :modal-component-name)} [:span {:class (stl/css :modal-component-name)}
(:name item)]])]])] (:name item)]])]])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input
{:class (stl/css :cancel-button)
:type "button"
:value cancel-label
:on-click cancel-fn}])
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input [:input
{:class (stl/css-case :accept-btn true {:class (stl/css :cancel-button)
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button" :type "button"
:value accept-label :value cancel-label
:on-click accept-fn}]]]]] :on-click cancel-fn}])
[:input
[:div.modal-overlay {:class (stl/css-case :accept-btn true
[:div.modal-container.confirm-dialog :danger (= accept-style :danger)
[:div.modal-header :primary (= accept-style :primary))
[:div.modal-header-title :type "button"
[:h2 title]] :value accept-label
[:div.modal-close-button :on-click accept-fn}]]]]]))
{:on-click cancel-fn} i/close]]
[:div.modal-content
(when (and (string? message) (not= message ""))
[:h3 message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 scd-message])
(when (string? hint)
[:p hint])
(when (> (count items) 0)
[:*
[:p (tr "ds.component-subtitle")]
[:ul.component-list
(for [item items]
[:li.modal-item-element
[:span.modal-component-icon i/component]
[:span (:name item)]])]])]
[:div.modal-footer
[:div.action-buttons
(when-not (= cancel-label :omit)
[:input.cancel-button
{:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]])))

View File

@ -11,56 +11,63 @@
&.transparent { &.transparent {
background-color: transparent; background-color: transparent;
} }
.modal-container { }
@extend .modal-container-base;
.modal-header { .modal-container {
margin-bottom: $s-24; @extend .modal-container-base;
.modal-title { }
@include tabTitleTipography;
color: var(--modal-title-foreground-color); .modal-header {
} margin-bottom: $s-24;
.modal-close-btn { }
@extend .modal-close-btn-base;
} .modal-title {
} @include tabTitleTipography;
.modal-content { color: var(--modal-title-foreground-color);
@include titleTipography; }
margin-bottom: $s-24;
.component-list { .modal-close-btn {
.modal-item-element { @extend .modal-close-btn-base;
@include flexRow; }
.modal-component-icon {
@include flexCenter; .modal-content {
height: $s-16; @include titleTipography;
width: $s-16; margin-bottom: $s-24;
svg { }
@extend .button-icon-small;
stroke: var(--color); .modal-item-element {
} @include flexRow;
} }
.modal-component-name {
@include titleTipography; .modal-component-icon {
} @include flexCenter;
} height: $s-16;
} width: $s-16;
.modal-hint { svg {
@extend .modal-hint-base; @extend .button-icon-small;
} stroke: var(--color);
} }
.modal-footer { }
.action-buttons { .modal-component-name {
@extend .modal-action-btns; @include titleTipography;
.cancel-button { }
@extend .modal-cancel-btn;
} .modal-hint {
.accept-btn { @extend .modal-hint-base;
@extend .modal-accept-btn; }
&.danger {
@extend .modal-danger-btn; .action-buttons {
} @extend .modal-action-btns;
} }
}
} .cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
} }
} }

View File

@ -53,8 +53,7 @@
(mf/defc dashboard-content (mf/defc dashboard-content
[{:keys [team projects project section search-term profile] :as props}] [{:keys [team projects project section search-term profile] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [container (mf/use-ref)
container (mf/use-ref)
content-width (mf/use-state 0) content-width (mf/use-state 0)
project-id (:id project) project-id (:id project)
team-id (:id team) team-id (:id team)
@ -82,123 +81,65 @@
(mf/use-effect on-resize) (mf/use-effect on-resize)
(if new-css-system [:div {:class (stl/css :dashboard-content)
[:div {:class (stl/css :dashboard-content) :on-click clear-selected-fn :ref container}
:on-click clear-selected-fn :ref container} (case section
(case section :dashboard-projects
:dashboard-projects [:*
[:* [:& projects-section
[:& projects-section {:team team
{:team team :projects projects
:projects projects :profile profile
:profile profile :default-project-id default-project-id}]
:default-project-id default-project-id}]
(when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile
:project-id project-id
:team-id team-id
:default-project-id default-project-id
:content-width @content-width}])]
:dashboard-fonts
[:& fonts-page {:team team}]
:dashboard-font-providers
[:& font-providers-page {:team team}]
:dashboard-files
(when project
[:*
[:& files-section {:team team :project project}]
(when (contains? cf/flags :dashboard-templates-section) (when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile [:& templates-section {:profile profile
:project-id project-id
:team-id team-id :team-id team-id
:default-project-id default-project-id
:content-width @content-width}])]
:dashboard-fonts
[:& fonts-page {:team team}]
:dashboard-font-providers
[:& font-providers-page {:team team}]
:dashboard-files
(when project
[:*
[:& files-section {:team team :project project}]
(when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile
:team-id team-id
:project-id project-id
:default-project-id default-project-id
:content-width @content-width}])])
:dashboard-search
[:& search-page {:team team
:search-term search-term}]
:dashboard-libraries
[:& libraries-page {:team team}]
:dashboard-team-members
[:& team-members-page {:team team :profile profile}]
:dashboard-team-invitations
[:& team-invitations-page {:team team}]
:dashboard-team-webhooks
[:& team-webhooks-page {:team team}]
:dashboard-team-settings
[:& team-settings-page {:team team :profile profile}]
nil)]
;; OLD
[:div.dashboard-content {:on-click clear-selected-fn :ref container}
(case section
:dashboard-projects
[:*
[:& projects-section
{:team team
:projects projects
:profile profile
:default-project-id default-project-id}]
(when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile
:project-id project-id :project-id project-id
:team-id team-id
:default-project-id default-project-id :default-project-id default-project-id
:content-width @content-width}])] :content-width @content-width}])])
:dashboard-fonts :dashboard-search
[:& fonts-page {:team team}] [:& search-page {:team team
:search-term search-term}]
:dashboard-font-providers :dashboard-libraries
[:& font-providers-page {:team team}] [:& libraries-page {:team team}]
:dashboard-files :dashboard-team-members
(when project [:& team-members-page {:team team :profile profile}]
[:*
[:& files-section {:team team :project project}]
(when (contains? cf/flags :dashboard-templates-section)
[:& templates-section {:profile profile
:team-id team-id
:project-id project-id
:default-project-id default-project-id
:content-width @content-width}])])
:dashboard-search :dashboard-team-invitations
[:& search-page {:team team [:& team-invitations-page {:team team}]
:search-term search-term}]
:dashboard-libraries :dashboard-team-webhooks
[:& libraries-page {:team team}] [:& team-webhooks-page {:team team}]
:dashboard-team-members :dashboard-team-settings
[:& team-members-page {:team team :profile profile}] [:& team-settings-page {:team team :profile profile}]
:dashboard-team-invitations nil)]))
[:& team-invitations-page {:team team}]
:dashboard-team-webhooks
[:& team-webhooks-page {:team team}]
:dashboard-team-settings
[:& team-settings-page {:team team :profile profile}]
nil)])))
(mf/defc dashboard (mf/defc dashboard
[{:keys [route profile] :as props}] [{:keys [route profile] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [section (get-in route [:data :name])
section (get-in route [:data :name])
params (parse-params route) params (parse-params route)
project-id (:project-id params) project-id (:project-id params)
@ -227,59 +168,31 @@
(fn [] (fn []
(events/unlistenByKey key)))) (events/unlistenByKey key))))
(if new-css-system [:& (mf/provider ctx/current-team-id) {:value team-id}
[:& (mf/provider ctx/current-team-id) {:value team-id} [:& (mf/provider ctx/current-project-id) {:value project-id}
[:& (mf/provider ctx/current-project-id) {:value project-id} ;; NOTE: dashboard events and other related functions assumes
;; NOTE: dashboard events and other related functions assumes ;; that the team is a implicit context variable that is
;; that the team is a implicit context variable that is ;; available using react context or accessing
;; available using react context or accessing ;; the :current-team-id on the state. We set the key to the
;; the :current-team-id on the state. We set the key to the ;; team-id because we want to completely refresh all the
;; team-id because we want to completely refresh all the ;; components on team change. Many components assumes that the
;; components on team change. Many components assumes that the ;; team is already set so don't put the team into mf/deps.
;; team is already set so don't put the team into mf/deps. (when team
(when team [:main {:class (stl/css :dashboard)
[:main {:class (stl/css :dashboard) :key (:id team)}
:key (:id team)} [:& sidebar
[:& sidebar {:team team
{:team team :projects projects
:projects projects :project project
:project project :profile profile
:section section
:search-term search-term}]
(when (and team profile (seq projects))
[:& dashboard-content
{:projects projects
:profile profile :profile profile
:section section
:search-term search-term}]
(when (and team profile (seq projects))
[:& dashboard-content
{:projects projects
:profile profile
:project project
:section section
:search-term search-term
:team team}])])]]
[:& (mf/provider ctx/current-team-id) {:value team-id}
[:& (mf/provider ctx/current-project-id) {:value project-id}
;; NOTE: dashboard events and other related functions assumes
;; that the team is a implicit context variable that is
;; available using react context or accessing
;; the :current-team-id on the state. We set the key to the
;; team-id because we want to completely refresh all the
;; components on team change. Many components assumes that the
;; team is already set so don't put the team into mf/deps.
(when team
[:main {:class (dom/classnames :dashboard-layout true) :key (:id team)}
[:& sidebar
{:team team
:projects projects
:project project :project project
:profile profile
:section section :section section
:search-term search-term}] :search-term search-term
(when (and team profile (seq projects)) :team team}])])]]))
[:& dashboard-content
{:projects projects
:profile profile
:project project
:section section
:search-term search-term
:team team}])])]])))

View File

@ -12,7 +12,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -26,8 +25,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :leave-and-reassign} ::mf/register-as :leave-and-reassign}
[{:keys [profile team accept]}] [{:keys [profile team accept]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form :spec ::leave-modal-form :initial {})
form (fm/use-form :spec ::leave-modal-form :initial {})
members-map (mf/deref refs/dashboard-team-members) members-map (mf/deref refs/dashboard-team-members)
members (vals members-map) members (vals members-map)
@ -42,71 +40,37 @@
(let [member-id (get-in @form [:clean-data :member-id])] (let [member-id (get-in @form [:clean-data :member-id])]
(accept member-id)))] (accept member-id)))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")]
[:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click on-cancel} i/close-refactor]]
:on-click on-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:p {:class (stl/css :modal-msg)}
(tr "modals.leave-and-reassign.hint1" (:name team))]
(if (empty? members)
[:p {:class (stl/css :modal-msg)} [:p {:class (stl/css :modal-msg)}
(tr "modals.leave-and-reassign.hint1" (:name team))] (tr "modals.leave-and-reassign.forbidden")]
[:*
[:& fm/form {:form form}
[:& fm/select {:name :member-id
:options options}]]])]
(if (empty? members) [:div {:class (stl/css :modal-footer)}
[:p {:class (stl/css :modal-msg)} [:div {:class (stl/css :action-buttons)}
(tr "modals.leave-and-reassign.forbidden")] [:input {:class (stl/css :cancel-button)
[:* :type "button"
[:& fm/form {:form form} :value (tr "labels.cancel")
[:& fm/select {:name :member-id :on-click on-cancel}]
:options options}]]])]
[:div {:class (stl/css :modal-footer)} [:input.accept-button
[:div {:class (stl/css :action-buttons)} {:type "button"
[:input {:class (stl/css :cancel-button) :class (stl/css-case :accept-btn true
:type "button" :danger (:valid @form)
:value (tr "labels.cancel") :global/disabled (not (:valid @form)))
:on-click on-cancel}] :disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
[:input.accept-button :on-click on-accept}]]]]]))
{:type "button"
:class (stl/css-case :accept-btn true
:danger (:valid @form)
:global/disabled (not (:valid @form)))
:disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
:on-click on-accept}]]]]]
[:div.modal-overlay
[:div.modal-container.confirm-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.leave-and-reassign.title")]]
[:div.modal-close-button
{:on-click on-cancel} i/close]]
[:div.modal-content.generic-form
[:p (tr "modals.leave-and-reassign.hint1" (:name team))]
(if (empty? members)
[:p (tr "modals.leave-and-reassign.forbidden")]
[:*
[:& fm/form {:form form}
[:& fm/select {:name :member-id
:options options}]]])]
[:div.modal-footer
[:div.action-buttons
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input.accept-button
{:type "button"
:class (if (:valid @form) "danger" "btn-disabled")
:disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
:on-click on-accept}]]]]])))

View File

@ -8,39 +8,46 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color); .modal-container {
.modal-header { @extend .modal-container-base;
margin-bottom: $s-24; border: $s-1 solid var(--modal-border-color);
.modal-title { }
@include tabTitleTipography;
color: var(--modal-title-foreground-color); .modal-header {
} margin-bottom: $s-24;
.modal-close-btn { }
@extend .modal-close-btn-base;
} .modal-title {
} @include tabTitleTipography;
.modal-content { color: var(--modal-title-foreground-color);
@include titleTipography; }
margin-bottom: $s-24;
.input-wrapper { .modal-close-btn {
@extend .input-with-label; @extend .modal-close-btn-base;
} }
}
.modal-footer { .modal-content {
.action-buttons { @include titleTipography;
@extend .modal-action-btns; margin-bottom: $s-24;
.cancel-button { }
@extend .modal-cancel-btn;
} .input-wrapper {
.accept-btn { @extend .input-with-label;
@extend .modal-accept-btn; }
&.danger {
@extend .modal-danger-btn; .action-buttons {
} @extend .modal-action-btns;
} }
}
} .cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
} }
} }

View File

@ -14,9 +14,7 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.comments :as cmt] [app.main.ui.comments :as cmt]
[app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[potok.v2.core :as ptk] [potok.v2.core :as ptk]
@ -42,21 +40,18 @@
(on-show-comments event))))] (on-show-comments event))))]
[:div {:class (stl/css :dashboard-comments-section)} [:div {:class (stl/css :dashboard-comments-section)}
[:button [:button {:tab-index "0"
{:tab-index "0" :on-click on-show-comments
:on-click on-show-comments :on-key-down handle-keydown
:on-key-down handle-keydown :data-test "open-comments"
:data-test "open-comments" :class (stl/css-case :button true
:class (stl/css-case :button true :open show?
:open show? :unread (boolean (seq tgroups)))}
:unread (boolean (seq tgroups)))} i/comments-refactor]]))
i/chat]]))
(mf/defc comments-section (mf/defc comments-section
[{:keys [profile team show? on-show-comments on-hide-comments]}] [{:keys [profile team show? on-hide-comments]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [threads-map (mf/deref refs/comment-threads)
threads-map (mf/deref refs/comment-threads)
users (mf/deref refs/current-team-comments-users) users (mf/deref refs/current-team-comments-users)
team-id (:id team) team-id (:id team)
@ -91,79 +86,32 @@
(st/emit! (ptk/event ::ev/event {::ev/name "open-comment-notifications" (st/emit! (ptk/event ::ev/event {::ev/name "open-comment-notifications"
::ev/origin "dashboard"}))))) ::ev/origin "dashboard"})))))
(if new-css-system [:div {:class (stl/css :dashboard-comments-section)}
[:div {:class (stl/css :dashboard-comments-section)} [:& dropdown {:show show? :on-close on-hide-comments}
[:& dropdown {:show show? :on-close on-hide-comments} [:div {:class (stl/css :dropdown :comments-section :comment-threads-section)}
[:div {:class (stl/css :dropdown :comments-section :comment-threads-section)} [:div {:class (stl/css :header)}
[:div {:class (stl/css :header)} [:h3 (tr "labels.comments")]
[:h3 (tr "labels.comments")] [:button
[:button {:class (stl/css :close)
{:class (stl/css :close) :tab-index (if show? "0" "-1")
:tab-index (if show? "0" "-1") :on-click on-hide-comments
:on-click on-hide-comments :on-key-down handle-keydown} i/close]]
:on-key-down handle-keydown} i/close]]
(if (seq tgroups) (if (seq tgroups)
[:div {:class (stl/css :thread-groups)} [:div {:class (stl/css :thread-groups)}
[:& cmt/comment-thread-group
{:group (first tgroups)
:on-thread-click on-navigate
:show-file-name true
:users users}]
(for [tgroup (rest tgroups)]
[:& cmt/comment-thread-group [:& cmt/comment-thread-group
{:group (first tgroups) {:group tgroup
:on-thread-click on-navigate :on-thread-click on-navigate
:show-file-name true :show-file-name true
:users users}] :users users
(for [tgroup (rest tgroups)] :key (:page-id tgroup)}])]
[:& cmt/comment-thread-group
{:group tgroup
:on-thread-click on-navigate
:show-file-name true
:users users
:key (:page-id tgroup)}])]
[:div {:class (stl/css :thread-groups-placeholder)} [:div {:class (stl/css :thread-groups-placeholder)}
i/chat i/comments-refactor
(tr "labels.no-comments-available")])]]] (tr "labels.no-comments-available")])]]]))
;; OLD
[:div.dashboard-comments-section
[:div.button
{:tab-index "0"
:on-click on-show-comments
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-show-comments event)))
:data-test "open-comments"
:class (dom/classnames :open show?
:unread (boolean (seq tgroups)))}
i/chat]
[:& dropdown {:show show? :on-close on-hide-comments}
[:div.dropdown.comments-section.comment-threads-section.
[:div.header
[:h3 (tr "labels.comments")]
[:span.close {:tab-index (if show? "0" "-1")
:on-click on-hide-comments
:on-key-down handle-keydown}
i/close]]
[:hr]
(if (seq tgroups)
[:div.thread-groups
[:& cmt/comment-thread-group
{:group (first tgroups)
:on-thread-click on-navigate
:show-file-name true
:users users}]
(for [tgroup (rest tgroups)]
[:*
[:hr]
[:& cmt/comment-thread-group
{:group tgroup
:on-thread-click on-navigate
:show-file-name true
:users users
:key (:page-id tgroup)}]])]
[:div.thread-groups-placeholder
i/chat
(tr "labels.no-comments-available")])]]])))

View File

@ -47,9 +47,11 @@
font-size: $fs-12; font-size: $fs-12;
padding: $s-24; padding: $s-24;
text-align: center; text-align: center;
color: $df-secondary;
svg { svg {
fill: $df-secondary; stroke: $df-secondary;
fill: none;
height: $s-24; height: $s-24;
margin-bottom: $s-24; margin-bottom: $s-24;
width: $s-24; width: $s-24;
@ -65,21 +67,22 @@
width: $s-32; width: $s-32;
svg { svg {
width: $s-16; min-width: $s-16;
height: $s-16; min-height: $s-16;
fill: $df-secondary; stroke: $df-secondary;
fill: none;
} }
&.unread svg, &.unread svg,
&.open svg { &.open svg {
fill: $da-tertiary; stroke: $da-tertiary;
} }
&:hover { &:hover {
background-color: $db-cuaternary; background-color: $db-cuaternary;
svg { svg {
fill: $da-primary; stroke: $da-primary;
} }
} }
} }

View File

@ -11,7 +11,6 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.worker :as uw] [app.main.worker :as uw]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -24,36 +23,19 @@
(mf/defc export-entry (mf/defc export-entry
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [file]}] [{:keys [file]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css-case :file-entry true
:loading (:loading? file)
:success (:export-success? file)
:error (:export-error? file))}
(if new-css-system [:div {:class (stl/css :file-name)}
[:div {:class (stl/css-case :file-entry true [:span {:class (stl/css :file-icon)}
:loading (:loading? file) (cond (:export-success? file) i/tick-refactor
:success (:export-success? file) (:export-error? file) i/close-refactor
:error (:export-error? file))} (:loading? file) i/loader-pencil)]
[:div {:class (stl/css :file-name)} [:div {:class (stl/css :file-name-label)}
[:span {:class (stl/css :file-icon)} (:name file)]]])
(cond (:export-success? file) i/tick-refactor
(:export-error? file) i/close-refactor
(:loading? file) i/loader-pencil)]
[:div {:class (stl/css :file-name-label)}
(:name file)]]]
[:div.file-entry
{:class (dom/classnames
:loading (:loading? file)
:success (:export-success? file)
:error (:export-error? file))}
[:div.file-name
[:div.file-icon
(cond (:export-success? file) i/tick
(:export-error? file) i/close
(:loading? file) i/loader-pencil)]
[:div.file-name-label (:name file)]]])))
(defn- mark-file-error (defn- mark-file-error
[files file-id] [files file-id]
@ -79,8 +61,7 @@
::mf/register-as :export ::mf/register-as :export
::mf/wrap-props false} ::mf/wrap-props false}
[{:keys [team-id files has-libraries? binary? features]}] [{:keys [team-id files has-libraries? binary? features]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [state* (mf/use-state
state* (mf/use-state
#(let [files (mapv (fn [file] (assoc file :loading? true)) files)] #(let [files (mapv (fn [file] (assoc file :loading? true)) files)]
{:status :prepare {:status :prepare
:selected :all :selected :all
@ -140,136 +121,70 @@
(when-not has-libraries? (when-not has-libraries?
(start-export))) (start-export)))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)}
[:h2 {:class (stl/css :modal-title)} (tr "dashboard.export.title")]
(tr "dashboard.export.title")] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click on-cancel} i/close-refactor]]
:on-click on-cancel} i/close-refactor]]
(cond (cond
(= status :prepare) (= status :prepare)
[:* [:*
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")] [:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")]
[:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")] [:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")]
(for [type export-types] (for [type export-types]
[:div {:class (stl/css :export-option true) [:div {:class (stl/css :export-option true)
:key (name type)} :key (name type)}
[:label {:for (str "export-" type) [:label {:for (str "export-" type)
:class (stl/css-case :global/checked (= selected type))} :class (stl/css-case :global/checked (= selected type))}
;; Execution time translation strings: ;; Execution time translation strings:
;; dashboard.export.options.all.message ;; dashboard.export.options.all.message
;; dashboard.export.options.all.title ;; dashboard.export.options.all.title
;; dashboard.export.options.detach.message ;; dashboard.export.options.detach.message
;; dashboard.export.options.detach.title ;; dashboard.export.options.detach.title
;; dashboard.export.options.merge.message ;; dashboard.export.options.merge.message
;; dashboard.export.options.merge.title ;; dashboard.export.options.merge.title
[:span {:class (stl/css-case :global/checked (= selected type))} [:span {:class (stl/css-case :global/checked (= selected type))}
(when (= selected type) (when (= selected type)
i/status-tick-refactor)] i/status-tick-refactor)]
[:div {:class (stl/css :option-content)} [:div {:class (stl/css :option-content)}
[:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))] [:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
[:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]] [:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]]
[:input {:type "radio" [:input {:type "radio"
:class (stl/css :option-input) :class (stl/css :option-input)
:id (str "export-" type) :id (str "export-" type)
:checked (= selected type) :checked (= selected type)
:name "export-option" :name "export-option"
:data-type (name type) :data-type (name type)
:on-change on-change}]]])] :on-change on-change}]]])]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :cancel-button) [:input {:class (stl/css :cancel-button)
:type "button" :type "button"
:value (tr "labels.cancel") :value (tr "labels.cancel")
:on-click on-cancel}] :on-click on-cancel}]
[:input {:class (stl/css :accept-btn) [:input {:class (stl/css :accept-btn)
:type "button" :type "button"
:value (tr "labels.continue") :value (tr "labels.continue")
:on-click on-accept}]]]] :on-click on-accept}]]]]
(= status :exporting) (= status :exporting)
[:* [:*
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(for [file (:files state)] (for [file (:files state)]
[:& export-entry {:file file :key (dm/str (:id file))}])] [:& export-entry {:file file :key (dm/str (:id file))}])]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :accept-btn) [:input {:class (stl/css :accept-btn)
:type "button" :type "button"
:value (tr "labels.close") :value (tr "labels.close")
:disabled (->> state :files (some :loading?)) :disabled (->> state :files (some :loading?))
:on-click on-cancel}]]]])]] :on-click on-cancel}]]]])]]))
[:div.modal-overlay
[:div.modal-container.export-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "dashboard.export.title")]]
[:div.modal-close-button
{:on-click on-cancel} i/close]]
(cond
(= status :prepare)
[:*
[:div.modal-content
[:p.explain (tr "dashboard.export.explain")]
[:p.detail (tr "dashboard.export.detail")]
(for [type export-types]
[:div.export-option {:class (when (= selected type) "selected")
:key (name type)}
[:label.option-container
;; Execution time translation strings:
;; dashboard.export.options.all.message
;; dashboard.export.options.all.title
;; dashboard.export.options.detach.message
;; dashboard.export.options.detach.title
;; dashboard.export.options.merge.message
;; dashboard.export.options.merge.title
[:h3 (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
[:p (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]
[:input {:type "radio"
:checked (= selected type)
:data-type (name type)
:on-change on-change
:name "export-option"}]
[:span {:class "option-radio-check"}]]])]
[:div.modal-footer
[:div.action-buttons
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.continue")
:on-click on-accept}]]]]
(= status :exporting)
[:*
[:div.modal-content
(for [file (:files state)]
[:& export-entry {:file file :key (dm/str (:id file))}])]
[:div.modal-footer
[:div.action-buttons
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.close")
:disabled (->> state :files (some :loading?))
:on-click on-cancel}]]]])]])))

View File

@ -8,59 +8,64 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
}
.modal-container { .modal-container {
@extend .modal-container-base; @extend .modal-container-base;
.modal-header { }
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-header {
@include titleTipography; margin-bottom: $s-24;
margin-bottom: $s-24; }
.export-option {
@extend .input-checkbox;
width: 100%;
align-items: flex-start;
label {
align-items: flex-start;
.modal-subtitle {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
}
span {
margin-top: $s-8;
}
.option-content {
@include flexColumn;
@include titleTipography;
}
}
}
.modal-footer { .modal-title {
.action-buttons { @include tabTitleTipography;
@extend .modal-action-btns; color: var(--modal-title-foreground-color);
.cancel-button { }
@extend .modal-cancel-btn;
} .modal-close-btn {
.accept-btn { @extend .modal-close-btn-base;
@extend .modal-accept-btn; }
&.danger {
@extend .modal-danger-btn; .modal-content {
} @include titleTipography;
} margin-bottom: $s-24;
} }
.export-option {
@extend .input-checkbox;
width: 100%;
align-items: flex-start;
label {
align-items: flex-start;
.modal-subtitle {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
} }
} }
span {
margin-top: $s-8;
}
}
.option-content {
@include flexColumn;
@include titleTipography;
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
} }
.modal-scd-msg, .modal-scd-msg,

View File

@ -11,7 +11,6 @@
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]] [app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]] [app.main.ui.dashboard.project-menu :refer [project-menu]]
@ -26,8 +25,7 @@
(mf/defc header (mf/defc header
[{:keys [project create-fn] :as props}] [{:keys [project create-fn] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [local (mf/use-state
local (mf/use-state
{:menu-open false {:menu-open false
:edition false}) :edition false})
@ -64,137 +62,75 @@
(dd/clear-selected-files))))] (dd/clear-selected-files))))]
(if new-css-system [:header {:class (stl/css :dashboard-header)}
[:header {:class (stl/css :dashboard-header)} (if (:is-default project)
(if (:is-default project) [:div#dashboard-drafts-title {:class (stl/css :dashboard-title)}
[:div#dashboard-drafts-title {:class (stl/css :dashboard-title)} [:h1 (tr "labels.drafts")]]
[:h1 (tr "labels.drafts")]]
(if (:edition @local) (if (:edition @local)
[:& inline-edition [:& inline-edition
{:content (:name project) {:content (:name project)
:on-end (fn [name] :on-end (fn [name]
(let [name (str/trim name)] (let [name (str/trim name)]
(when-not (str/empty? name) (when-not (str/empty? name)
(st/emit! (-> (dd/rename-project (assoc project :name name)) (st/emit! (-> (dd/rename-project (assoc project :name name))
(with-meta {::ev/origin "project"})))) (with-meta {::ev/origin "project"}))))
(swap! local assoc :edition false)))}] (swap! local assoc :edition false)))}]
[:div {:class (stl/css :dashboard-title)} [:div {:class (stl/css :dashboard-title)}
[:h1 {:on-double-click on-edit [:h1 {:on-double-click on-edit
:data-test "project-title" :data-test "project-title"
:id (:id project)} :id (:id project)}
(:name project)]])) (:name project)]]))
[:& project-menu {:project project [:& project-menu {:project project
:show? (:menu-open @local) :show? (:menu-open @local)
:left (- (:x (:menu-pos @local)) 180) :left (- (:x (:menu-pos @local)) 180)
:top (:y (:menu-pos @local)) :top (:y (:menu-pos @local))
:on-edit on-edit :on-edit on-edit
:on-menu-close on-menu-close :on-menu-close on-menu-close
:on-import on-import}] :on-import on-import}]
[:div {:class (stl/css :dashboard-header-actions)} [:div {:class (stl/css :dashboard-header-actions)}
[:a [:a
{:class (stl/css :btn-secondary :btn-small) {:class (stl/css :btn-secondary :btn-small)
:tab-index "0"
:on-click on-create-click
:data-test "new-file"
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-create-click event)))}
(tr "dashboard.new-file")]
(when-not (:is-default project)
[:button
{:class (stl/css-case :icon true
:pin-icon true
:tooltip true
:tooltip-bottom true
:active (:is-pinned project))
:tab-index "0" :tab-index "0"
:on-click on-create-click :on-click toggle-pin
:data-test "new-file" :alt (tr "dashboard.pin-unpin")
:on-key-down (fn [event] :on-key-down (fn [event]
(when (kbd/enter? event) (when (kbd/enter? event)
(on-create-click event)))} (toggle-pin event)))}
(tr "dashboard.new-file")] (if (:is-pinned project)
i/pin-fill
i/pin)])
(when-not (:is-default project) [:div
[:button {:class (stl/css :icon :tooltip :tooltip-bottom-left)
{:class (stl/css-case :icon true :tab-index "0"
:pin-icon true :on-click on-menu-click
:tooltip true :alt (tr "dashboard.options")
:tooltip-bottom true :on-key-down (fn [event]
:active (:is-pinned project)) (when (kbd/enter? event)
:tab-index "0" (on-menu-click event)))}
:on-click toggle-pin i/actions]]]))
:alt (tr "dashboard.pin-unpin")
:on-key-down (fn [event]
(when (kbd/enter? event)
(toggle-pin event)))}
(if (:is-pinned project)
i/pin-fill
i/pin)])
[:div
{:class (stl/css :icon :tooltip :tooltip-bottom-left)
:tab-index "0"
:on-click on-menu-click
:alt (tr "dashboard.options")
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-menu-click event)))}
i/actions]]]
;; OLD
[:header.dashboard-header
(if (:is-default project)
[:div.dashboard-title#dashboard-drafts-title
[:h1 (tr "labels.drafts")]]
(if (:edition @local)
[:& inline-edition {:content (:name project)
:on-end (fn [name]
(let [name (str/trim name)]
(when-not (str/empty? name)
(st/emit! (-> (dd/rename-project (assoc project :name name))
(with-meta {::ev/origin "project"}))))
(swap! local assoc :edition false)))}]
[:div.dashboard-title
[:h1 {:on-double-click on-edit
:data-test "project-title"
:id (:id project)}
(:name project)]]))
[:& project-menu {:project project
:show? (:menu-open @local)
:left (- (:x (:menu-pos @local)) 180)
:top (:y (:menu-pos @local))
:on-edit on-edit
:on-menu-close on-menu-close
:on-import on-import}]
[:div.dashboard-header-actions
[:a.btn-secondary.btn-small
{:tab-index "0"
:on-click on-create-click
:data-test "new-file"
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-create-click event)))}
(tr "dashboard.new-file")]
(when-not (:is-default project)
[:button.icon.pin-icon.tooltip.tooltip-bottom
{:tab-index "0"
:class (when (:is-pinned project) "active")
:on-click toggle-pin
:alt (tr "dashboard.pin-unpin")
:on-key-down (fn [event]
(when (kbd/enter? event)
(toggle-pin event)))}
(if (:is-pinned project)
i/pin-fill
i/pin)])
[:div.icon.tooltip.tooltip-bottom-left
{:tab-index "0"
:on-click on-menu-click
:alt (tr "dashboard.options")
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-menu-click event)))}
i/actions]]])))
(mf/defc files-section (mf/defc files-section
[{:keys [project team] :as props}] [{:keys [project team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [files-map (mf/deref refs/dashboard-files)
files-map (mf/deref refs/dashboard-files)
project-id (:id project) project-id (:id project)
[rowref limit] (hooks/use-dynamic-grid-item-width) [rowref limit] (hooks/use-dynamic-grid-item-width)
@ -233,28 +169,15 @@
(st/emit! (dd/fetch-files {:project-id project-id}) (st/emit! (dd/fetch-files {:project-id project-id})
(dd/clear-selected-files))) (dd/clear-selected-files)))
(if new-css-system [:*
[:* [:& header {:team team
[:& header {:team team :project project
:project project :create-fn create-file}]
:create-fn create-file}] [:section {:class (stl/css :dashboard-container :no-bg)
[:section {:class (stl/css :dashboard-container :no-bg) :ref rowref}
:ref rowref} [:& grid {:project project
[:& grid {:project project :files files
:files files :origin :files
:origin :files :create-fn create-file
:create-fn create-file :limit limit}]]]))
:limit limit}]]]
;; OLD
[:*
[:& header {:team team
:project project
:create-fn create-file}]
[:section.dashboard-container.no-bg {:ref rowref}
[:& grid {:project project
:files files
:origin :files
:create-fn create-file
:limit limit}]]])))

View File

@ -15,7 +15,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.context-menu :refer [context-menu]] [app.main.ui.components.context-menu :refer [context-menu]]
[app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -40,17 +39,10 @@
(mf/defc header (mf/defc header
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [section team] :as props}] [{:keys [section team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (use-set-page-title team section)
(use-set-page-title team section) [:header {:class (stl/css :dashboard-header)}
(if new-css-system [:div#dashboard-fonts-title {:class (stl/css :dashboard-title)}
[:header {:class (stl/css :dashboard-header)} [:h1 (tr "labels.fonts")]]])
[:div#dashboard-fonts-title {:class (stl/css :dashboard-title)}
[:h1 (tr "labels.fonts")]]]
;; OLD
[:header.dashboard-header
[:div.dashboard-title#dashboard-fonts-title
[:h1 (tr "labels.fonts")]]])))
(mf/defc font-variant-display-name (mf/defc font-variant-display-name
[{:keys [variant]}] [{:keys [variant]}]
@ -61,8 +53,7 @@
(mf/defc fonts-upload (mf/defc fonts-upload
[{:keys [team installed-fonts] :as props}] [{:keys [team installed-fonts] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [fonts (mf/use-state {})
fonts (mf/use-state {})
input-ref (mf/use-ref) input-ref (mf/use-ref)
uploading (mf/use-state #{}) uploading (mf/use-state #{})
@ -121,151 +112,82 @@
handle-dismiss-all handle-dismiss-all
(mf/use-callback (mf/deps @fonts) #(on-dismiss-all (vals @fonts)))] (mf/use-callback (mf/deps @fonts) #(on-dismiss-all (vals @fonts)))]
(if new-css-system [:div {:class (stl/css :dashboard-fonts-upload)}
[:div {:class (stl/css :dashboard-fonts-upload)} [:div {:class (stl/css :dashboard-fonts-hero)}
[:div {:class (stl/css :dashboard-fonts-hero)} [:div {:class (stl/css :desc)}
[:div {:class (stl/css :desc)} [:h2 (tr "labels.upload-custom-fonts")]
[:h2 (tr "labels.upload-custom-fonts")] [:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
[:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
[:button [:button
{:class (stl/css :btn-primary) {:class (stl/css :btn-primary)
:on-click on-click :on-click on-click
:tab-index "0"} :tab-index "0"}
[:span (tr "labels.add-custom-font")] [:span (tr "labels.add-custom-font")]
[:& file-uploader {:input-id "font-upload" [:& file-uploader {:input-id "font-upload"
:accept cm/str-font-types :accept cm/str-font-types
:multi true :multi true
:ref input-ref :ref input-ref
:on-selected on-selected}]] :on-selected on-selected}]]
[:div {:class (stl/css :banner)} [:div {:class (stl/css :banner)}
[:div {:class (stl/css :icon)} i/msg-info] [:div {:class (stl/css :icon)} i/msg-info]
[:div {:class (stl/css :content)}
[:& i18n/tr-html {:tag-name "span"
:label "dashboard.fonts.hero-text2"}]]]
(when problematic-fonts?
[:div {:class (stl/css :banner :warning)}
[:div {:class (stl/css :icon)} i/msg-warning]
[:div {:class (stl/css :content)} [:div {:class (stl/css :content)}
[:& i18n/tr-html {:tag-name "span" [:& i18n/tr-html {:tag-name "span"
:label "dashboard.fonts.hero-text2"}]]] :label "dashboard.fonts.warning-text"}]]])]]
(when problematic-fonts? [:*
[:div {:class (stl/css :banner :warning)} (when (some? (vals @fonts))
[:div {:class (stl/css :icon)} i/msg-warning] [:div {:class (stl/css :font-item :table-row)}
[:div {:class (stl/css :content)} [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
[:& i18n/tr-html {:tag-name "span" [:div {:class (stl/css :table-field :options)}
:label "dashboard.fonts.warning-text"}]]])]] [:button {:class (stl/css :btn-primary)
:on-click handle-upload-all :data-test "upload-all"}
[:span (tr "dashboard.fonts.upload-all")]]
[:button {:class (stl/css :btn-secondary)
:on-click handle-dismiss-all :data-test "dismiss-all"}
[:span (tr "dashboard.fonts.dismiss-all")]]]])
(for [item (sort-by :font-family (vals @fonts))]
(let [uploading? (contains? @uploading (:id item))]
[:div {:class (stl/css :font-item :table-row) :key (:id item)}
[:div {:class (stl/css :table-field :family)}
[:input {:type "text"
:on-blur #(on-blur-name (:id item) %)
:default-value (:font-family item)}]]
[:div {:class (stl/css :table-field :variants)}
[:span {:class (stl/css :label)}
[:& font-variant-display-name {:variant item}]]]
[:div {:class (stl/css :table-field :filenames)}
(for [item (:names item)]
[:span item])]
[:*
(when (some? (vals @fonts))
[:div {:class (stl/css :font-item :table-row)}
[:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:button {:class (stl/css :btn-primary) (when (:height-warning? item)
:on-click handle-upload-all :data-test "upload-all"} [:span {:class (stl/css :icon :failure)} i/msg-warning])
[:span (tr "dashboard.fonts.upload-all")]]
[:button {:class (stl/css :btn-secondary)
:on-click handle-dismiss-all :data-test "dismiss-all"}
[:span (tr "dashboard.fonts.dismiss-all")]]]])
(for [item (sort-by :font-family (vals @fonts))] [:button
(let [uploading? (contains? @uploading (:id item))] {:on-click #(on-upload item)
[:div {:class (stl/css :font-item :table-row) :key (:id item)} :class (stl/css-case :btn-primary true
[:div {:class (stl/css :table-field :family)} :upload-button true
[:input {:type "text" :disabled uploading?)
:on-blur #(on-blur-name (:id item) %) :disabled uploading?}
:default-value (:font-family item)}]] (if uploading?
[:div {:class (stl/css :table-field :variants)} (tr "labels.uploading")
[:span {:class (stl/css :label)} (tr "labels.upload"))]
[:& font-variant-display-name {:variant item}]]] [:span {:class (stl/css :icon :close)
:on-click #(on-delete item)} i/close]]]))]]))
[:div {:class (stl/css :table-field :filenames)}
(for [item (:names item)]
[:span item])]
[:div {:class (stl/css :table-field :options)}
(when (:height-warning? item)
[:span {:class (stl/css :icon :failure)} i/msg-warning])
[:button
{:on-click #(on-upload item)
:class (stl/css-case :btn-primary true
:upload-button true
:disabled uploading?)
:disabled uploading?}
(if uploading?
(tr "labels.uploading")
(tr "labels.upload"))]
[:span {:class (stl/css :icon :close)
:on-click #(on-delete item)} i/close]]]))]]
;; OLD
[:div.dashboard-fonts-upload
[:div.dashboard-fonts-hero
[:div.desc
[:h2 (tr "labels.upload-custom-fonts")]
[:& i18n/tr-html {:label "dashboard.fonts.hero-text1"}]
[:div.banner
[:div.icon i/msg-info]
[:div.content
[:& i18n/tr-html {:tag-name "span"
:label "dashboard.fonts.hero-text2"}]]]
(when problematic-fonts?
[:div.banner.warning
[:div.icon i/msg-warning]
[:div.content
[:& i18n/tr-html {:tag-name "span"
:label "dashboard.fonts.warning-text"}]]])]
[:button.btn-primary
{:on-click on-click
:tab-index "0"}
[:span (tr "labels.add-custom-font")]
[:& file-uploader {:input-id "font-upload"
:accept cm/str-font-types
:multi true
:ref input-ref
:on-selected on-selected}]]]
[:*
(when (some? (vals @fonts))
[:div.font-item.table-row
[:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
[:div.table-field.options
[:div.btn-primary
{:on-click #(on-upload-all (vals @fonts)) :data-test "upload-all"}
[:span (tr "dashboard.fonts.upload-all")]]
[:div.btn-secondary
{:on-click #(on-dismiss-all (vals @fonts)) :data-test "dismiss-all"}
[:span (tr "dashboard.fonts.dismiss-all")]]]])
(for [item (sort-by :font-family (vals @fonts))]
(let [uploading? (contains? @uploading (:id item))]
[:div.font-item.table-row {:key (:id item)}
[:div.table-field.family
[:input {:type "text"
:on-blur #(on-blur-name (:id item) %)
:default-value (:font-family item)}]]
[:div.table-field.variants
[:span.label
[:& font-variant-display-name {:variant item}]]]
[:div.table-field.filenames
(for [item (:names item)]
[:span item])]
[:div.table-field.options
(when (:height-warning? item)
[:span.icon.failure i/msg-warning])
[:button.btn-primary.upload-button
{:on-click #(on-upload item)
:class (dom/classnames :disabled uploading?)
:disabled uploading?}
(if uploading?
(tr "labels.uploading")
(tr "labels.upload"))]
[:span.icon.close {:on-click #(on-delete item)} i/close]]]))]])))
(mf/defc installed-font (mf/defc installed-font
[{:keys [font-id variants] :as props}] [{:keys [font-id variants] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [font (first variants)
font (first variants)
variants (sort-by (fn [item] variants (sort-by (fn [item]
[(:font-weight item) [(:font-weight item)
@ -324,94 +246,52 @@
:on-accept (fn [_props] :on-accept (fn [_props]
(delete-variant-fn id))})))] (delete-variant-fn id))})))]
(if new-css-system [:div {:class (stl/css :font-item :table-row)}
[:div {:class (stl/css :font-item :table-row)} [:div {:class (stl/css :table-field :family)}
[:div {:class (stl/css :table-field :family)} (if @edit?
(if @edit? [:input {:type "text"
[:input {:type "text" :default-value @state
:default-value @state :on-key-down on-key-down
:on-key-down on-key-down :on-change on-change}]
:on-change on-change}] [:span (:font-family font)])]
[:span (:font-family font)])]
[:div {:class (stl/css :table-field :variants)} [:div {:class (stl/css :table-field :variants)}
(for [item variants] (for [item variants]
[:div {:class (stl/css :variant)} [:div {:class (stl/css :variant)}
[:span {:class (stl/css :label)} [:span {:class (stl/css :label)}
[:& font-variant-display-name {:variant item}]] [:& font-variant-display-name {:variant item}]]
[:span [:span
{:class (stl/css :icon :close) {:class (stl/css :icon :close)
:on-click #(on-delete-variant (:id item))} :on-click #(on-delete-variant (:id item))}
i/plus]])] i/plus]])]
(if @edit? (if @edit?
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:button [:button
{:disabled (str/blank? @state) {:disabled (str/blank? @state)
:on-click on-save :on-click on-save
:class (stl/css-case :btn-primary true :class (stl/css-case :btn-primary true
:btn-disabled (str/blank? @state))} :btn-disabled (str/blank? @state))}
(tr "labels.save")] (tr "labels.save")]
[:button {:class (stl/css :icon :close) [:button {:class (stl/css :icon :close)
:on-click on-cancel} i/close]] :on-click on-cancel} i/close]]
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:span {:class (stl/css :icon) [:span {:class (stl/css :icon)
:on-click #(reset! open-menu? true)} i/actions] :on-click #(reset! open-menu? true)} i/actions]
[:& context-menu [:& context-menu
{:on-close #(reset! open-menu? false) {:on-close #(reset! open-menu? false)
:show @open-menu? :show @open-menu?
:fixed? false :fixed? false
:top -15 :top -15
:left -115 :left -115
:options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"] :options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"]
[(tr "labels.delete") on-delete nil "font-delete"]]}]])] [(tr "labels.delete") on-delete nil "font-delete"]]}]])]))
;;OLD
[:div.font-item.table-row
[:div.table-field.family
(if @edit?
[:input {:type "text"
:default-value @state
:on-key-down on-key-down
:on-change on-change}]
[:span (:font-family font)])]
[:div.table-field.variants
(for [item variants]
[:div.variant
[:span.label
[:& font-variant-display-name {:variant item}]]
[:span.icon.close
{:on-click #(on-delete-variant (:id item))}
i/plus]])]
[:div]
(if @edit?
[:div.table-field.options
[:button.btn-primary
{:disabled (str/blank? @state)
:on-click on-save
:class (dom/classnames :btn-disabled (str/blank? @state))}
(tr "labels.save")]
[:span.icon.close {:on-click on-cancel} i/close]]
[:div.table-field.options
[:span.icon {:on-click #(reset! open-menu? true)} i/actions]
[:& context-menu
{:on-close #(reset! open-menu? false)
:show @open-menu?
:fixed? false
:top -15
:left -115
:options [[(tr "labels.edit") #(reset! edit? true) nil "font-edit"]
[(tr "labels.delete") on-delete nil "font-delete"]]}]])])))
(mf/defc installed-fonts (mf/defc installed-fonts
[{:keys [fonts] :as props}] [{:keys [fonts] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [sterm (mf/use-state "")
sterm (mf/use-state "")
matches? matches?
#(str/includes? (str/lower (:font-family %)) @sterm) #(str/includes? (str/lower (:font-family %)) @sterm)
@ -422,98 +302,49 @@
(let [val (dom/get-target-val event)] (let [val (dom/get-target-val event)]
(reset! sterm (str/lower val)))))] (reset! sterm (str/lower val)))))]
(if new-css-system [:div {:class (stl/css :dashboard-installed-fonts)}
[:div {:class (stl/css :dashboard-installed-fonts)} [:h3 (tr "labels.installed-fonts")]
[:h3 (tr "labels.installed-fonts")] [:div {:class (stl/css :installed-fonts-header)}
[:div {:class (stl/css :installed-fonts-header)} [:div {:class (stl/css :table-field :family)} (tr "labels.font-family")]
[:div {:class (stl/css :table-field :family)} (tr "labels.font-family")] [:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")]
[:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")] [:div {:class (stl/css :table-field :search-input)}
[:div {:class (stl/css :table-field :search-input)} [:input {:placeholder (tr "labels.search-font")
[:input {:placeholder (tr "labels.search-font") :default-value ""
:default-value "" :on-change on-change}]]]
:on-change on-change}]]]
(cond (cond
(seq fonts) (seq fonts)
(for [[font-id variants] (->> (vals fonts) (for [[font-id variants] (->> (vals fonts)
(filter matches?) (filter matches?)
(group-by :font-id))] (group-by :font-id))]
[:& installed-font {:key (str font-id) [:& installed-font {:key (str font-id)
:font-id font-id :font-id font-id
:variants variants}]) :variants variants}])
(nil? fonts) (nil? fonts)
[:div {:class (stl/css :fonts-placeholder)} [:div {:class (stl/css :fonts-placeholder)}
[:div {:class (stl/css :icon)} i/loader] [:div {:class (stl/css :icon)} i/loader]
[:div {:class (stl/css :label)} (tr "dashboard.loading-fonts")]] [:div {:class (stl/css :label)} (tr "dashboard.loading-fonts")]]
:else :else
[:div {:class (stl/css :fonts-placeholder)} [:div {:class (stl/css :fonts-placeholder)}
[:div {:class (stl/css :icon)} i/text] [:div {:class (stl/css :icon)} i/text]
[:div {:class (stl/css :label)} (tr "dashboard.fonts.empty-placeholder")]])] [:div {:class (stl/css :label)} (tr "dashboard.fonts.empty-placeholder")]])]))
;; OLD
[:div.dashboard-installed-fonts
[:h3 (tr "labels.installed-fonts")]
[:div.installed-fonts-header
[:div.table-field.family (tr "labels.font-family")]
[:div.table-field.variants (tr "labels.font-variants")]
[:div]
[:div.table-field.search-input
[:input {:placeholder (tr "labels.search-font")
:default-value ""
:on-change on-change}]]]
(cond
(seq fonts)
(for [[font-id variants] (->> (vals fonts)
(filter matches?)
(group-by :font-id))]
[:& installed-font {:key (str font-id)
:font-id font-id
:variants variants}])
(nil? fonts)
[:div.fonts-placeholder
[:div.icon i/loader]
[:div.label (tr "dashboard.loading-fonts")]]
:else
[:div.fonts-placeholder
[:div.icon i/text]
[:div.label (tr "dashboard.fonts.empty-placeholder")]])])))
(mf/defc fonts-page (mf/defc fonts-page
[{:keys [team] :as props}] [{:keys [team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [fonts (mf/deref refs/dashboard-fonts)]
fonts (mf/deref refs/dashboard-fonts)] [:*
(if new-css-system [:& header {:team team :section :fonts}]
[:* [:section {:class (stl/css :dashboard-container :dashboard-fonts)}
[:& header {:team team :section :fonts}] [:& fonts-upload {:team team :installed-fonts fonts}]
[:section {:class (stl/css :dashboard-container :dashboard-fonts)} [:& installed-fonts {:team team :fonts fonts}]]]))
[:& fonts-upload {:team team :installed-fonts fonts}]
[:& installed-fonts {:team team :fonts fonts}]]]
;; OLD
[:*
[:& header {:team team :section :fonts}]
[:section.dashboard-container.dashboard-fonts
[:& fonts-upload {:team team :installed-fonts fonts}]
[:& installed-fonts {:team team :fonts fonts}]]])))
(mf/defc font-providers-page (mf/defc font-providers-page
[{:keys [team] :as props}] [{:keys [team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:*
(if new-css-system [:& header {:team team :section :providers}]
[:* [:section {:class (stl/css :dashboard-container)}
[:& header {:team team :section :providers}] [:span "font providers"]]])
[:section {:class (stl/css :dashboard-container)}
[:span "font providers"]]]
;; OLD
[:*
[:& header {:team team :section :providers}]
[:section.dashboard-container
[:span "font providers"]]])))

View File

@ -20,7 +20,6 @@
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.color-bullet :as bc] [app.main.ui.components.color-bullet :as bc]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.file-menu :refer [file-menu]] [app.main.ui.dashboard.file-menu :refer [file-menu]]
[app.main.ui.dashboard.import :refer [use-import-file]] [app.main.ui.dashboard.import :refer [use-import-file]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
@ -68,8 +67,7 @@
(mf/defc grid-item-thumbnail (mf/defc grid-item-thumbnail
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [file-id revn thumbnail-uri background-color]}] [{:keys [file-id revn thumbnail-uri background-color]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [container (mf/use-ref)
container (mf/use-ref)
visible? (h/use-visible container :once? true)] visible? (h/use-visible container :once? true)]
(mf/with-effect [file-id revn visible? thumbnail-uri] (mf/with-effect [file-id revn visible? thumbnail-uri]
@ -83,28 +81,16 @@
:revn revn :revn revn
:message (ex-message cause))))))) :message (ex-message cause)))))))
(if new-css-system [:div {:class (stl/css :grid-item-th)
[:div {:class (stl/css :grid-item-th) :style {:background-color background-color}
:style {:background-color background-color} :ref container}
:ref container} (when visible?
(when visible? (if thumbnail-uri
(if thumbnail-uri [:img {:class (stl/css :grid-item-thumbnail-image)
[:img {:class (stl/css :grid-item-thumbnail-image) :src thumbnail-uri
:src thumbnail-uri :loading "lazy"
:loading "lazy" :decoding "async"}]
:decoding "async"}] i/loader-pencil))]))
i/loader-pencil))]
;; OLD
[:div.grid-item-th
{:style {:background-color background-color}
:ref container}
(when visible?
(if thumbnail-uri
[:img.grid-item-thumbnail-image {:src thumbnail-uri
:loading "lazy"
:decoding "async"}]
i/loader-pencil))])))
;; --- Grid Item Library ;; --- Grid Item Library
@ -112,228 +98,125 @@
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [file] :as props}] [{:keys [file] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (mf/with-effect [file]
(mf/with-effect [file] (when file
(when file (let [font-ids (map :font-id (get-in file [:library-summary :typographies :sample] []))]
(let [font-ids (map :font-id (get-in file [:library-summary :typographies :sample] []))] (run! fonts/ensure-loaded! font-ids))))
(run! fonts/ensure-loaded! font-ids))))
(if new-css-system [:div {:class (stl/css :grid-item-th :library)}
[:div {:class (stl/css :grid-item-th :library)} (if (nil? file)
(if (nil? file) i/loader-pencil
i/loader-pencil (let [summary (:library-summary file)
(let [summary (:library-summary file) components (:components summary)
components (:components summary) colors (:colors summary)
colors (:colors summary) typographies (:typographies summary)]
typographies (:typographies summary)] [:*
[:* (when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies)))
(when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies))) [:*
[:* [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-title)}
[:div {:class (stl/css :asset-title)} [:span (tr "workspace.assets.components")]
[:span (tr "workspace.assets.components")] [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
[:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-title)}
[:div {:class (stl/css :asset-title)} [:span (tr "workspace.assets.colors")]
[:span (tr "workspace.assets.colors")] [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
[:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-title)}
[:div {:class (stl/css :asset-title)} [:span (tr "workspace.assets.typography")]
[:span (tr "workspace.assets.typography")] [:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
[:span {:class (stl/css :num-assets)} (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
(when (pos? (:count components)) (when (pos? (:count components))
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-title)} [:div {:class (stl/css :asset-title)}
[:span (tr "workspace.assets.components")] [:span (tr "workspace.assets.components")]
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
[:div {:class (stl/css :asset-list)} [:div {:class (stl/css :asset-list)}
(for [component (:sample components)] (for [component (:sample components)]
(let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library (let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
[:div {:class (stl/css :asset-list-item) [:div {:class (stl/css :asset-list-item)
:key (str "assets-component-" (:id component))} :key (str "assets-component-" (:id component))}
[:& component-svg {:root-shape (get-in component [:objects root-id]) [:& component-svg {:root-shape (get-in component [:objects root-id])
:objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2 :objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :item-name) [:span {:class (stl/css :item-name)
:title (:name component)} :title (:name component)}
(:name component)]]])) (:name component)]]]))
(when (> (:count components) (count (:sample components))) (when (> (:count components) (count (:sample components)))
[:div {:class (stl/css :asset-list-item)} [:div {:class (stl/css :asset-list-item)}
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :item-name)} "(...)"]]])]]) [:span {:class (stl/css :item-name)} "(...)"]]])]])
(when (pos? (:count colors)) (when (pos? (:count colors))
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-title)} [:div {:class (stl/css :asset-title)}
[:span (tr "workspace.assets.colors")] [:span (tr "workspace.assets.colors")]
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space
[:div {:class (stl/css :asset-list)} [:div {:class (stl/css :asset-list)}
(for [color (:sample colors)] (for [color (:sample colors)]
(let [default-name (cond (let [default-name (cond
(:gradient color) (uc/gradient-type->string (get-in color [:gradient :type])) (:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
(:color color) (:color color) (:color color) (:color color)
:else (:value color))] :else (:value color))]
[:div {:class (stl/css :asset-list-item) [:div {:class (stl/css :asset-list-item)
:key (str "assets-color-" (:id color))} :key (str "assets-color-" (:id color))}
[:& bc/color-bullet {:color {:color (:color color) [:& bc/color-bullet {:color {:color (:color color)
:opacity (:opacity color)}}] :opacity (:opacity color)}}]
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :color-name)} (:name color)] [:span {:class (stl/css :color-name)} (:name color)]
(when-not (= (:name color) default-name) (when-not (= (:name color) default-name)
[:span {:class (stl/css :color-value)} (:color color)])]])) [:span {:class (stl/css :color-value)} (:color color)])]]))
(when (> (:count colors) (count (:sample colors))) (when (> (:count colors) (count (:sample colors)))
[:div {:class (stl/css :asset-list-item)} [:div {:class (stl/css :asset-list-item)}
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :item-name)} "(...)"]]])]]) [:span {:class (stl/css :item-name)} "(...)"]]])]])
(when (pos? (:count typographies)) (when (pos? (:count typographies))
[:div {:class (stl/css :asset-section)} [:div {:class (stl/css :asset-section)}
[:div {:class (stl/css :asset-title)} [:div {:class (stl/css :asset-title)}
[:span (tr "workspace.assets.typography")] [:span (tr "workspace.assets.typography")]
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space
[:div {:class (stl/css :asset-list)} [:div {:class (stl/css :asset-list)}
(for [typography (:sample typographies)] (for [typography (:sample typographies)]
[:div {:class (stl/css :asset-list-item) [:div {:class (stl/css :asset-list-item)
:key (str "assets-typography-" (:id typography))} :key (str "assets-typography-" (:id typography))}
[:div {:class (stl/css :typography-sample) [:div {:class (stl/css :typography-sample)
:style {:font-family (:font-family typography) :style {:font-family (:font-family typography)
:font-weight (:font-weight typography) :font-weight (:font-weight typography)
:font-style (:font-style typography)}} :font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")] (tr "workspace.assets.typography.sample")]
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :item-name) [:span {:class (stl/css :item-name)
:title (:name typography)} :title (:name typography)}
(:name typography)]]]) (:name typography)]]])
(when (> (:count typographies) (count (:sample typographies))) (when (> (:count typographies) (count (:sample typographies)))
[:div {:class (stl/css :asset-list-item)} [:div {:class (stl/css :asset-list-item)}
[:div {:class (stl/css :name-block)} [:div {:class (stl/css :name-block)}
[:span {:class (stl/css :item-name)} "(...)"]]])]])]))] [:span {:class (stl/css :item-name)} "(...)"]]])]])]))])
;; OLD
[:div.grid-item-th.library
(if (nil? file)
i/loader-pencil
(let [summary (:library-summary file)
components (:components summary)
colors (:colors summary)
typographies (:typographies summary)]
[:*
(when (and (zero? (:count components)) (zero? (:count colors)) (zero? (:count typographies)))
[:*
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.components")]
[:span.num-assets (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.colors")]
[:span.num-assets (str "\u00A0(") 0 ")"]]] ;; Unicode 00A0 is non-breaking space
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.typography")]
[:span.num-assets (str "\u00A0(") 0 ")"]]]]) ;; Unicode 00A0 is non-breaking space
(when (pos? (:count components))
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.components")]
[:span.num-assets (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
[:div.asset-list
(for [component (:sample components)]
(let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
[:div.asset-list-item {:key (str "assets-component-" (:id component))}
[:& component-svg {:root-shape (get-in component [:objects root-id])
:objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
[:div.name-block
[:span.item-name {:title (:name component)}
(:name component)]]]))
(when (> (:count components) (count (:sample components)))
[:div.asset-list-item
[:div.name-block
[:span.item-name "(...)"]]])]])
(when (pos? (:count colors))
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.colors")]
[:span.num-assets (str "\u00A0(") (:count colors) ")"]] ;; Unicode 00A0 is non-breaking space
[:div.asset-list
(for [color (:sample colors)]
(let [default-name (cond
(:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
(:color color) (:color color)
:else (:value color))]
[:div.asset-list-item {:key (str "assets-color-" (:id color))}
[:& bc/color-bullet {:color {:color (:color color)
:opacity (:opacity color)}}]
[:div.name-block
[:span.color-name (:name color)]
(when-not (= (:name color) default-name)
[:span.color-value (:color color)])]]))
(when (> (:count colors) (count (:sample colors)))
[:div.asset-list-item
[:div.name-block
[:span.item-name "(...)"]]])]])
(when (pos? (:count typographies))
[:div.asset-section
[:div.asset-title
[:span (tr "workspace.assets.typography")]
[:span.num-assets (str "\u00A0(") (:count typographies) ")"]] ;; Unicode 00A0 is non-breaking space
[:div.asset-list
(for [typography (:sample typographies)]
[:div.asset-list-item {:key (str "assets-typography-" (:id typography))}
[:div.typography-sample
{:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
[:div.name-block
[:span.item-name {:title (:name typography)}
(:name typography)]]])
(when (> (:count typographies) (count (:sample typographies)))
[:div.asset-list-item
[:div.name-block
[:span.item-name "(...)"]]])]])]))])))
;; --- Grid Item ;; --- Grid Item
(mf/defc grid-item-metadata (mf/defc grid-item-metadata
[{:keys [modified-at]}] [{:keys [modified-at]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [locale (mf/deref i18n/locale)
locale (mf/deref i18n/locale)
time (dt/timeago modified-at {:locale locale})] time (dt/timeago modified-at {:locale locale})]
(if new-css-system [:span {:class (stl/css :date)} time]))
[:span {:class (stl/css :date)} time]
;; OLD
[:span.date time])))
(defn create-counter-element (defn create-counter-element
[_element file-count new-css-system] [_element file-count]
(if new-css-system (let [counter-el (dom/create-element "div")]
(let [counter-el (dom/create-element "div")] (dom/set-property! counter-el "class" (stl/css :drag-counter))
(dom/set-property! counter-el "class" (stl/css :drag-counter)) (dom/set-text! counter-el (str file-count))
(dom/set-text! counter-el (str file-count)) counter-el))
counter-el)
(let [counter-el (dom/create-element "div")]
(dom/set-property! counter-el "class" "drag-counter")
(dom/set-text! counter-el (str file-count))
counter-el)))
(mf/defc grid-item (mf/defc grid-item
{:wrap [mf/memo]} {:wrap [mf/memo]}
[{:keys [file navigate? origin library-view?] :as props}] [{:keys [file navigate? origin library-view?] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [file-id (:id file)
file-id (:id file)
local (mf/use-state {:menu-open false local (mf/use-state {:menu-open false
:menu-pos nil :menu-pos nil
:edition false}) :edition false})
@ -380,8 +263,7 @@
item-el item-el
(if select-current? (if select-current?
1 1
(count selected-files)) (count selected-files)))]
new-css-system)]
(when select-current? (when select-current?
(st/emit! (dd/clear-selected-files)) (st/emit! (dd/clear-selected-files))
(st/emit! (dd/toggle-file-select file))) (st/emit! (dd/toggle-file-select file)))
@ -453,132 +335,67 @@
(when (and (not selected?) (:menu-open @local)) (when (and (not selected?) (:menu-open @local))
(swap! local assoc :menu-open false))) (swap! local assoc :menu-open false)))
(if new-css-system [:li
[:li {:class (stl/css-case :grid-item true :project-th true :library library-view?)}
{:class (stl/css-case :grid-item true :project-th true :library library-view?)} [:button
[:button {:class (stl/css-case :selected selected? :library library-view?)
{:class (stl/css-case :selected selected? :library library-view?) :ref node-ref
:ref node-ref :title (:name file)
:title (:name file) :draggable true
:draggable true :on-click on-select
:on-click on-select :on-key-down handle-key-down
:on-key-down handle-key-down :on-double-click on-navigate
:on-double-click on-navigate :on-drag-start on-drag-start
:on-drag-start on-drag-start :on-context-menu on-menu-click}
:on-context-menu on-menu-click}
[:div {:class (stl/css :overlay)}] [:div {:class (stl/css :overlay)}]
(if library-view? (if library-view?
[:& grid-item-library {:file file}] [:& grid-item-library {:file file}]
[:& grid-item-thumbnail [:& grid-item-thumbnail
{:file-id (:id file) {:file-id (:id file)
:revn (:revn file) :revn (:revn file)
:thumbnail-uri (:thumbnail-uri file) :thumbnail-uri (:thumbnail-uri file)
:background-color (dm/get-in file [:data :options :background])}]) :background-color (dm/get-in file [:data :options :background])}])
(when (and (:is-shared file) (not library-view?)) (when (and (:is-shared file) (not library-view?))
[:div {:class (stl/css :item-badge)} i/library]) [:div {:class (stl/css :item-badge)} i/library])
[:div {:class (stl/css :info-wrapper)} [:div {:class (stl/css :info-wrapper)}
[:div {:class (stl/css :item-info)} [:div {:class (stl/css :item-info)}
(if (:edition @local) (if (:edition @local)
[:& inline-edition {:content (:name file) [:& inline-edition {:content (:name file)
:on-end edit}] :on-end edit}]
[:h3 (:name file)]) [:h3 (:name file)])
[:& grid-item-metadata {:modified-at (:modified-at file)}]] [:& grid-item-metadata {:modified-at (:modified-at file)}]]
[:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open @local))} [:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open @local))}
[:div [:div
{:class (stl/css :project-th-icon :menu) {:class (stl/css :project-th-icon :menu)
:tab-index "0" :tab-index "0"
:ref menu-ref :ref menu-ref
:id (str file-id "-action-menu") :id (str file-id "-action-menu")
:on-click on-menu-click :on-click on-menu-click
:on-key-down (fn [event] :on-key-down (fn [event]
(when (kbd/enter? event) (when (kbd/enter? event)
(dom/stop-propagation event) (dom/stop-propagation event)
(on-menu-click event)))} (on-menu-click event)))}
i/actions i/actions
(when selected? (when selected?
[:& file-menu {:files (vals selected-files) [:& file-menu {:files (vals selected-files)
:show? (:menu-open @local) :show? (:menu-open @local)
:left (+ 24 (:x (:menu-pos @local))) :left (+ 24 (:x (:menu-pos @local)))
:top (:y (:menu-pos @local)) :top (:y (:menu-pos @local))
:navigate? navigate? :navigate? navigate?
:on-edit on-edit :on-edit on-edit
:on-menu-close on-menu-close :on-menu-close on-menu-close
:origin origin :origin origin
:dashboard-local dashboard-local :dashboard-local dashboard-local
:parent-id (str file-id "-action-menu")}])]]]]] :parent-id (str file-id "-action-menu")}])]]]]]))
;; OLD
[:li.grid-item.project-th {:class (dom/classnames :library library-view?)}
[:button
{:tab-index "0"
:class (dom/classnames :selected selected?
:library library-view?)
:ref node-ref
:draggable true
:on-click on-select
:on-key-down (fn [event]
(dom/stop-propagation event)
(when (kbd/enter? event)
(on-navigate event))
(when (kbd/shift? event)
(when (or (kbd/down-arrow? event) (kbd/left-arrow? event) (kbd/up-arrow? event) (kbd/right-arrow? event))
(on-select event)) ;; TODO Fix this
))
:on-double-click on-navigate
:on-drag-start on-drag-start
:on-context-menu on-menu-click}
[:div.overlay]
(if library-view?
[:& grid-item-library {:file file}]
[:& grid-item-thumbnail
{:file-id (:id file)
:revn (:revn file)
:thumbnail-uri (:thumbnail-uri file)
:background-color (dm/get-in file [:data :options :background])}])
(when (and (:is-shared file) (not library-view?))
[:div.item-badge i/library])
[:div.info-wrapper
[:div.item-info
(if (:edition @local)
[:& inline-edition {:content (:name file)
:on-end edit}]
[:h3 (:name file)])
[:& grid-item-metadata {:modified-at (:modified-at file)}]]
[:div.project-th-actions {:class (dom/classnames
:force-display (:menu-open @local))}
[:div.project-th-icon.menu
{:tab-index "0"
:ref menu-ref
:id (str file-id "-action-menu")
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions
(when selected?
[:& file-menu {:files (vals selected-files)
:show? (:menu-open @local)
:left (+ 24 (:x (:menu-pos @local)))
:top (:y (:menu-pos @local))
:navigate? navigate?
:on-edit on-edit
:on-menu-close on-menu-close
:origin origin
:dashboard-local dashboard-local
:parent-id (str file-id "-action-menu")}])]]]]])))
(mf/defc grid (mf/defc grid
[{:keys [files project origin limit library-view? create-fn] :as props}] [{:keys [files project origin limit library-view? create-fn] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [dragging? (mf/use-state false)
dragging? (mf/use-state false)
project-id (:id project) project-id (:id project)
node-ref (mf/use-var nil) node-ref (mf/use-var nil)
@ -621,109 +438,58 @@
(reset! dragging? false) (reset! dragging? false)
(import-files (.-files (.-dataTransfer e))))))] (import-files (.-files (.-dataTransfer e))))))]
(if new-css-system [:div {:class (stl/css :dashboard-grid)
[:div :on-drag-enter on-drag-enter
{:class (stl/css :dashboard-grid) :on-drag-over on-drag-over
:on-drag-enter on-drag-enter :on-drag-leave on-drag-leave
:on-drag-over on-drag-over :on-drop on-drop
:on-drag-leave on-drag-leave :ref node-ref}
:on-drop on-drop
:ref node-ref}
(cond (cond
(nil? files) (nil? files)
[:& loading-placeholder] [:& loading-placeholder]
(seq files)
(for [slice (partition-all limit files)]
[:ul {:class (stl/css :grid-row)}
(when @dragging?
[:li {:class (stl/css :grid-item)}])
(for [item slice]
[:& grid-item
{:file item
:key (:id item)
:navigate? true
:origin origin
:library-view? library-view?}])])
:else
[:& empty-placeholder
{:limit limit
:create-fn create-fn
:origin origin}])]
;; OLD
[:div.dashboard-grid
{:on-drag-enter on-drag-enter
:on-drag-over on-drag-over
:on-drag-leave on-drag-leave
:on-drop on-drop
:ref node-ref}
(cond
(nil? files)
[:& loading-placeholder]
(seq files)
[:ul.grid-row
{:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
(seq files)
(for [slice (partition-all limit files)]
[:ul {:class (stl/css :grid-row)}
(when @dragging? (when @dragging?
[:li.grid-item]) [:li {:class (stl/css :grid-item)}])
(for [item slice]
(for [item files]
[:& grid-item [:& grid-item
{:file item {:file item
:key (:id item) :key (:id item)
:navigate? true :navigate? true
:origin origin :origin origin
:library-view? library-view?}])] :library-view? library-view?}])])
:else :else
[:& empty-placeholder [:& empty-placeholder
{:limit limit {:limit limit
:create-fn create-fn :create-fn create-fn
:origin origin}])]))) :origin origin}])]))
(mf/defc line-grid-row (mf/defc line-grid-row
[{:keys [files selected-files dragging? limit] :as props}] [{:keys [files selected-files dragging? limit] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [elements limit
elements limit
limit (if dragging? (dec limit) limit)] limit (if dragging? (dec limit) limit)]
(if new-css-system [:ul
[:ul {:class (stl/css :grid-row :no-wrap)
{:class (stl/css :grid-row :no-wrap) :style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
:style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
(when dragging? (when dragging?
[:li {:class (stl/css :grid-item :dragged)}]) [:li {:class (stl/css :grid-item :dragged)}])
(for [item (take limit files)] (for [item (take limit files)]
[:& grid-item [:& grid-item
{:id (:id item) {:id (:id item)
:file item :file item
:selected-files selected-files :selected-files selected-files
:key (:id item) :key (:id item)
:navigate? false}])] :navigate? false}])]))
;; OLD
[:ul.grid-row.no-wrap
{:style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
(when dragging?
[:li.grid-item.dragged])
(for [item (take limit files)]
[:& grid-item
{:id (:id item)
:file item
:selected-files selected-files
:key (:id item)
:navigate? false}])])))
(mf/defc line-grid (mf/defc line-grid
[{:keys [project team files limit create-fn] :as props}] [{:keys [project team files limit create-fn] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [dragging? (mf/use-state false)
dragging? (mf/use-state false)
project-id (:id project) project-id (:id project)
team-id (:id team) team-id (:id team)
@ -799,47 +565,24 @@
(reset! dragging? false) (reset! dragging? false)
(import-files (.-files (.-dataTransfer e)))))))] (import-files (.-files (.-dataTransfer e)))))))]
(if new-css-system [:div {:class (stl/css :dashboard-grid)
[:div {:class (stl/css :dashboard-grid) :on-drag-enter on-drag-enter
:on-drag-enter on-drag-enter :on-drag-over on-drag-over
:on-drag-over on-drag-over :on-drag-leave on-drag-leave
:on-drag-leave on-drag-leave :on-drop on-drop}
:on-drop on-drop} (cond
(cond (nil? files)
(nil? files) [:& loading-placeholder]
[:& loading-placeholder]
(seq files) (seq files)
[:& line-grid-row {:files files [:& line-grid-row {:files files
:team-id team-id :team-id team-id
:selected-files selected-files :selected-files selected-files
:dragging? @dragging? :dragging? @dragging?
:limit limit}] :limit limit}]
:else :else
[:& empty-placeholder [:& empty-placeholder
{:dragging? @dragging? {:dragging? @dragging?
:limit limit :limit limit
:create-fn create-fn}])] :create-fn create-fn}])]))
;; OLD
[:div.dashboard-grid {:on-drag-enter on-drag-enter
:on-drag-over on-drag-over
:on-drag-leave on-drag-leave
:on-drop on-drop}
(cond
(nil? files)
[:& loading-placeholder]
(seq files)
[:& line-grid-row {:files files
:team-id team-id
:selected-files selected-files
:dragging? @dragging?
:limit limit}]
:else
[:& empty-placeholder
{:dragging? @dragging?
:limit limit
:create-fn create-fn}])])))

View File

@ -18,7 +18,6 @@
[app.main.features :as features] [app.main.features :as features]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.worker :as uw] [app.main.worker :as uw]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -152,8 +151,7 @@
(mf/defc import-entry (mf/defc import-entry
[{:keys [state file editing? can-be-deleted?]}] [{:keys [state file editing? can-be-deleted?]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [loading? (or (= :analyzing (:status file))
loading? (or (= :analyzing (:status file))
(= :importing (:status file))) (= :importing (:status file)))
analyze-error? (= :analyze-error (:status file)) analyze-error? (= :analyze-error (:status file))
import-finish? (= :import-finish (:status file)) import-finish? (= :import-finish (:status file))
@ -191,122 +189,66 @@
(fn [] (fn []
(swap! state update :files remove-file (:file-id file))))] (swap! state update :files remove-file (:file-id file))))]
(if new-css-system [:div {:class (stl/css-case :file-entry true
[:div {:class (stl/css-case :file-entry true :loading loading?
:loading loading? :success (and import-finish? (not import-warn?) (not import-error?))
:success (and import-finish? (not import-warn?) (not import-error?)) :warning (and import-finish? import-warn? (not import-error?))
:warning (and import-finish? import-warn? (not import-error?)) :error (or import-error? analyze-error?)
:error (or import-error? analyze-error?) :editable (and ready? (not editing?)))}
:editable (and ready? (not editing?)))}
[:div {:class (stl/css :file-name)} [:div {:class (stl/css :file-name)}
[:div {:class (stl/css-case :file-icon true [:div {:class (stl/css-case :file-icon true
:icon-fill ready?)} :icon-fill ready?)}
(cond loading? i/loader-pencil (cond loading? i/loader-pencil
ready? i/logo-icon ready? i/logo-icon
import-warn? i/msg-warning import-warn? i/msg-warning
import-error? i/close-refactor import-error? i/close-refactor
import-finish? i/tick-refactor import-finish? i/tick-refactor
analyze-error? i/close-refactor)] analyze-error? i/close-refactor)]
(if editing? (if editing?
[:div {:class (stl/css :file-name-edit)} [:div {:class (stl/css :file-name-edit)}
[:input {:type "text" [:input {:type "text"
:auto-focus true :auto-focus true
:default-value (:name file) :default-value (:name file)
:on-key-press handle-edit-key-press :on-key-press handle-edit-key-press
:on-blur handle-edit-blur}]] :on-blur handle-edit-blur}]]
[:div {:class (stl/css :file-name-label)} [:div {:class (stl/css :file-name-label)}
(:name file) (:name file)
(when is-shared? i/library-refactor)]) (when is-shared? i/library-refactor)])
[:div {:class (stl/css :edit-entry-buttons)} [:div {:class (stl/css :edit-entry-buttons)}
(when (= "application/zip" (:type file)) (when (= "application/zip" (:type file))
[:button {:on-click handle-edit-entry} i/curve-refactor]) [:button {:on-click handle-edit-entry} i/curve-refactor])
(when can-be-deleted? (when can-be-deleted?
[:button {:on-click handle-remove-entry} i/delete-refactor])]] [:button {:on-click handle-remove-entry} i/delete-refactor])]]
(cond (cond
analyze-error? analyze-error?
[:div {:class (stl/css :error-message)} [:div {:class (stl/css :error-message)}
(tr "dashboard.import.analyze-error")] (tr "dashboard.import.analyze-error")]
import-error? import-error?
[:div {:class (stl/css :error-message)} [:div {:class (stl/css :error-message)}
(tr "dashboard.import.import-error")] (tr "dashboard.import.import-error")]
(and (not import-finish?) (some? progress)) (and (not import-finish?) (some? progress))
[:div {:class (stl/css :progress-message)} (parse-progress-message progress)]) [:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
[:div {:class (stl/css :linked-libraries)} [:div {:class (stl/css :linked-libraries)}
(for [library-id (:libraries file)] (for [library-id (:libraries file)]
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %)))) (let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
error? (or (:deleted? library-data) (:import-error library-data))] error? (or (:deleted? library-data) (:import-error library-data))]
(when (some? library-data) (when (some? library-data)
[:div {:class (stl/css-case :linked-library-tag true [:div {:class (stl/css-case :linked-library-tag true
:error error?)} :error error?)}
i/detach-refactor (:name library-data)])))]] i/detach-refactor (:name library-data)])))]]))
[:div.file-entry
{:class (dom/classnames
:loading loading?
:success (and import-finish? (not import-warn?) (not import-error?))
:warning (and import-finish? import-warn? (not import-error?))
:error (or import-error? analyze-error?)
:editable (and ready? (not editing?)))}
[:div.file-name
[:div.file-icon
(cond loading? i/loader-pencil
ready? i/logo-icon
import-warn? i/msg-warning
import-error? i/close
import-finish? i/tick
analyze-error? i/close)]
(if editing?
[:div.file-name-edit
[:input {:type "text"
:auto-focus true
:default-value (:name file)
:on-key-press handle-edit-key-press
:on-blur handle-edit-blur}]]
[:div.file-name-label (:name file) (when is-shared? i/library)])
[:div.edit-entry-buttons
(when (= "application/zip" (:type file))
[:button {:on-click handle-edit-entry} i/pencil])
(when can-be-deleted?
[:button {:on-click handle-remove-entry} i/trash])]]
(cond
analyze-error?
[:div.error-message
(tr "dashboard.import.analyze-error")]
import-error?
[:div.error-message
(tr "dashboard.import.import-error")]
(and (not import-finish?) (some? progress))
[:div.progress-message (parse-progress-message progress)])
[:div.linked-libraries
(for [library-id (:libraries file)]
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
error? (or (:deleted? library-data) (:import-error library-data))]
(when (some? library-data)
[:div.linked-library-tag {:class (when error? "error")}
(if error? i/unchain i/chain) (:name library-data)])))]])))
(mf/defc import-dialog (mf/defc import-dialog
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :import} ::mf/register-as :import}
[{:keys [project-id files template on-finish-import]}] [{:keys [project-id files template on-finish-import]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [state (mf/use-state
state (mf/use-state
{:status :analyzing {:status :analyzing
:editing nil :editing nil
:importing-templates 0 :importing-templates 0
@ -425,122 +367,60 @@
#(doseq [file files] #(doseq [file files]
(wapi/revoke-uri (:uri file))))) (wapi/revoke-uri (:uri file)))))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
[:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
[:button {:class (stl/css :modal-close-btn) [:button {:class (stl/css :modal-close-btn)
:on-click handle-cancel} i/close-refactor]] :on-click handle-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(when (and (= :importing (:status @state)) (not pending-import?)) (when (and (= :importing (:status @state)) (not pending-import?))
(if (> warning-files 0) (if (> warning-files 0)
[:div {:class (stl/css-case :feedback-banner true [:div {:class (stl/css-case :feedback-banner true
:warning true)} :warning true)}
[:div {:class (stl/css :icon)} i/msg-warning-refactor] [:div {:class (stl/css :icon)} i/msg-warning-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]] [:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]]
[:div {:class (stl/css :feedback-banner)} [:div {:class (stl/css :feedback-banner)}
[:div {:class (stl/css :icon)} i/msg-success-refactor] [:div {:class (stl/css :icon)} i/msg-success-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]])) [:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
(for [file files] (for [file files]
(let [editing? (and (some? (:file-id file)) (let [editing? (and (some? (:file-id file))
(= (:file-id file) (:editing @state)))] (= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
:key (dm/str (:uri file))
:file file
:editing? editing?
:can-be-deleted? (> (count files) 1)}]))
(when (some? template)
[:& import-entry {:state state [:& import-entry {:state state
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready)) :key (dm/str (:uri file))
:editing? false :file file
:can-be-deleted? false}])] :editing? editing?
:can-be-deleted? (> (count files) 1)}]))
[:div {:class (stl/css :modal-footer)} (when (some? template)
[:div {:class (stl/css :action-buttons)} [:& import-entry {:state state
(when (= :analyzing (:status @state)) :file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
[:input {:class (stl/css :cancel-button) :editing? false
:type "button" :can-be-deleted? false}])]
:value (tr "labels.cancel")
:on-click handle-cancel}])
(when (= :analyzing (:status @state)) [:div {:class (stl/css :modal-footer)}
[:input {:class (stl/css :accept-btn) [:div {:class (stl/css :action-buttons)}
:type "button" (when (= :analyzing (:status @state))
:value (tr "labels.continue") [:input {:class (stl/css :cancel-button)
:disabled (or pending-analysis? (not valid-files?)) :type "button"
:on-click handle-continue}]) :value (tr "labels.cancel")
:on-click handle-cancel}])
(when (= :importing (:status @state)) (when (= :analyzing (:status @state))
[:input {:class (stl/css :accept-btn) [:input {:class (stl/css :accept-btn)
:type "button" :type "button"
:value (tr "labels.accept") :value (tr "labels.continue")
:disabled (or pending-import? (not valid-files?)) :disabled (or pending-analysis? (not valid-files?))
:on-click handle-accept}])]]]] :on-click handle-continue}])
(when (= :importing (:status @state))
[:input {:class (stl/css :accept-btn)
[:div.modal-overlay :type "button"
[:div.modal-container.import-dialog :value (tr "labels.accept")
[:div.modal-header :disabled (or pending-import? (not valid-files?))
[:div.modal-header-title :on-click handle-accept}])]]]]))
[:h2 (tr "dashboard.import")]]
[:div.modal-close-button
{:on-click handle-cancel} i/close]]
[:div.modal-content
(when (and (= :importing (:status @state)) (not pending-import?))
(if (> warning-files 0)
[:div.feedback-banner.warning
[:div.icon i/msg-warning]
[:div.message (tr "dashboard.import.import-warning" warning-files success-files)]]
[:div.feedback-banner
[:div.icon i/checkbox-checked]
[:div.message (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
(for [file files]
(let [editing? (and (some? (:file-id file))
(= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
:key (dm/str (:uri file))
:file file
:editing? editing?
:can-be-deleted? (> (count files) 1)}]))
(when (some? template)
[:& import-entry {:state state
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
:editing? false
:can-be-deleted? false}])]
[:div.modal-footer
[:div.action-buttons
(when (= :analyzing (:status @state))
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click handle-cancel}])
(when (= :analyzing (:status @state))
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.continue")
:disabled (or pending-analysis? (not valid-files?))
:on-click handle-continue}])
(when (= :importing (:status @state))
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.accept")
:disabled (or pending-import? (not valid-files?))
:on-click handle-accept}])]]]])))

View File

@ -8,69 +8,72 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
}
.modal-container { .modal-container {
@extend .modal-container-base; @extend .modal-container-base;
border: $s-1 solid var(--modal-border-color); border: $s-1 solid var(--modal-border-color);
.modal-header { }
margin-bottom: $s-24;
.modal-title { .modal-header {
@include tabTitleTipography; margin-bottom: $s-24;
color: var(--modal-title-foreground-color); }
}
.modal-close-btn { .modal-title {
@extend .modal-close-btn-base; @include tabTitleTipography;
} color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.feedback-banner {
@include flexRow;
height: $s-32;
width: 100%;
margin-bottom: $s-24;
border-radius: $br-8;
background-color: var(--alert-background-color-ok);
color: var(--alert-foreground-color-ok);
.icon {
@include flexCenter;
height: $s-24;
width: $s-24;
svg {
@extend .button-icon;
stroke: var(--alert-foreground-color-ok);
} }
}
.modal-content { .message {
@include titleTipography; @include titleTipography;
margin-bottom: $s-24; }
.feedback-banner { &.warning {
@include flexRow; background-color: var(--alert-background-color-warning);
height: $s-32; color: var(--alert-foreground-color-warning);
width: 100%; .icon svg {
margin-bottom: $s-24; stroke: var(--alert-foreground-color-warning);
border-radius: $br-8;
background-color: var(--alert-background-color-ok);
color: var(--alert-foreground-color-ok);
.icon {
@include flexCenter;
height: $s-24;
width: $s-24;
svg {
@extend .button-icon;
stroke: var(--alert-foreground-color-ok);
}
}
.message {
@include titleTipography;
}
&.warning {
background-color: var(--alert-background-color-warning);
color: var(--alert-foreground-color-warning);
.icon svg {
stroke: var(--alert-foreground-color-warning);
}
}
}
} }
}
}
.modal-footer { .action-buttons {
.action-buttons { @extend .modal-action-btns;
@extend .modal-action-btns; }
.cancel-button {
@extend .modal-cancel-btn; .cancel-button {
} @extend .modal-cancel-btn;
.accept-btn { }
@extend .modal-accept-btn; .accept-btn {
&.danger { @extend .modal-accept-btn;
@extend .modal-danger-btn; &.danger {
} @extend .modal-danger-btn;
}
}
}
} }
} }
@ -122,6 +125,7 @@
.error-message, .error-message,
.progress-message { .progress-message {
height: $s-32; height: $s-32;
color: var(--modal-text-foreground-color);
} }
.linked-libraries { .linked-libraries {

View File

@ -7,7 +7,6 @@
(ns app.main.ui.dashboard.inline-edition (ns app.main.ui.dashboard.inline-edition
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
@ -15,8 +14,7 @@
(mf/defc inline-edition (mf/defc inline-edition
[{:keys [content on-end] :as props}] [{:keys [content on-end] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [name (mf/use-state content)
name (mf/use-state content)
input-ref (mf/use-ref) input-ref (mf/use-ref)
on-input on-input
@ -62,25 +60,14 @@
(dom/focus! node) (dom/focus! node)
(dom/select-text! node)))) (dom/select-text! node))))
(if new-css-system [:div {:class (stl/css :edit-wrapper)}
[:div {:class (stl/css :edit-wrapper)} [:input {:class (stl/css :element-title)
[:input {:class (stl/css :element-title) :value @name
:value @name :ref input-ref
:ref input-ref :on-click on-click
:on-click on-click :on-change on-input
:on-change on-input :on-key-down on-keyup
:on-key-down on-keyup :on-blur on-blur}]
:on-blur on-blur}] [:span {:class (stl/css :close)
[:span {:class (stl/css :close) :on-click on-cancel} i/close-refactor]]))
:on-click on-cancel} i/close]]
;; OLD
[:div.edit-wrapper
[:input.element-title {:value @name
:ref input-ref
:on-click on-click
:on-change on-input
:on-key-down on-keyup
:on-blur on-blur}]
[:span.close {:on-click on-cancel} i/close]])))

View File

@ -12,42 +12,42 @@
padding-right: $s-24; padding-right: $s-24;
position: relative; position: relative;
margin-right: $s-24; margin-right: $s-24;
}
input.element-title { input.element-title {
background-color: $db-primary; background-color: $db-primary;
border-radius: $br-8; border-radius: $br-8;
color: $df-primary; color: $df-primary;
font-size: $fs-16; font-size: $fs-16;
height: $s-32; height: $s-32;
margin: 0; margin: 0;
border: none; border: none;
padding: $s-6; padding: $s-6;
width: 100%; width: 100%;
&:focus-visible { &:focus-visible {
border: $s-1 solid $da-primary; border: $s-1 solid $da-primary;
outline: none; outline: none;
}
} }
}
.close { .close {
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
top: $s-1; top: $s-1;
right: calc(-1 * $s-8); right: calc(-1 * $s-8);
svg {
fill: $df-secondary;
height: $s-16;
transform: rotate(45deg) translateY(7px);
width: $s-16;
margin: 0;
}
&:hover {
svg { svg {
fill: $df-secondary; fill: var(--warning-color);
height: $s-16;
transform: rotate(45deg) translateY(7px);
width: $s-16;
margin: 0;
}
&:hover {
svg {
fill: var(--warning-color);
}
} }
} }
} }

View File

@ -12,7 +12,6 @@
[app.main.features :as features] [app.main.features :as features]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]] [app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -21,8 +20,7 @@
(mf/defc libraries-page (mf/defc libraries-page
[{:keys [team] :as props}] [{:keys [team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [files-map (mf/deref refs/dashboard-shared-files)
files-map (mf/deref refs/dashboard-shared-files)
projects (mf/deref refs/dashboard-projects) projects (mf/deref refs/dashboard-projects)
default-project (->> projects vals (d/seek :is-default)) default-project (->> projects vals (d/seek :is-default))
@ -49,27 +47,14 @@
(st/emit! (dd/fetch-shared-files (:id team)) (st/emit! (dd/fetch-shared-files (:id team))
(dd/clear-selected-files))) (dd/clear-selected-files)))
(if new-css-system [:*
[:* [:header {:class (stl/css :dashboard-header)}
[:header {:class (stl/css :dashboard-header)} [:div#dashboard-libraries-title {:class (stl/css :dashboard-title)}
[:div#dashboard-libraries-title {:class (stl/css :dashboard-title)} [:h1 (tr "dashboard.libraries-title")]]]
[:h1 (tr "dashboard.libraries-title")]]] [:section {:class (stl/css :dashboard-container :no-bg :dashboard-shared) :ref rowref}
[:section {:class (stl/css :dashboard-container :no-bg :dashboard-shared) :ref rowref} [:& grid {:files files
[:& grid {:files files :project default-project
:project default-project :origin :libraries
:origin :libraries :limit limit
:limit limit :library-view? components-v2}]]]))
:library-view? components-v2}]]]
;; OLD
[:*
[:header.dashboard-header {:ref rowref}
[:div.dashboard-title#dashboard-libraries-title
[:h1 (tr "dashboard.libraries-title")]]]
[:section.dashboard-container.no-bg.dashboard-shared
[:& grid {:files files
:project default-project
:origin :libraries
:limit limit
:library-view? components-v2}]]])))

View File

@ -7,65 +7,39 @@
(ns app.main.ui.dashboard.placeholder (ns app.main.ui.dashboard.placeholder
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc empty-placeholder (mf/defc empty-placeholder
[{:keys [dragging? limit origin create-fn] :as props}] [{:keys [dragging? limit origin create-fn] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-click
on-click
(mf/use-fn (mf/use-fn
(mf/deps create-fn) (mf/deps create-fn)
(fn [_] (fn [_]
(create-fn "dashboard:empty-folder-placeholder")))] (create-fn "dashboard:empty-folder-placeholder")))]
(if new-css-system (cond
(cond (true? dragging?)
(true? dragging?) [:ul
[:ul {:class (stl/css :grid-row :no-wrap)
{:class (stl/css :grid-row :no-wrap) :style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}} [:li {:class (stl/css :grid-item :grid-empty-placeholder :dragged)}]]
[:li {:class (stl/css :grid-item :grid-empty-placeholder :dragged)}]]
(= :libraries origin) (= :libraries origin)
[:div {:class (stl/css :grid-empty-placeholder :libs) [:div {:class (stl/css :grid-empty-placeholder :libs)
:data-test "empty-placeholder"} :data-test "empty-placeholder"}
[:div {:class (stl/css :text)} [:div {:class (stl/css :text)}
[:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]] [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]]
:else :else
[:div [:div
{:class (stl/css :grid-empty-placeholder)} {:class (stl/css :grid-empty-placeholder)}
[:button {:class (stl/css :create-new) [:button {:class (stl/css :create-new)
:on-click on-click} :on-click on-click}
i/add-refactor]]) i/add-refactor]])))
;; OLD
(cond
(true? dragging?)
[:ul.grid-row.no-wrap
{:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
[:li.grid-item]]
(= :libraries origin)
[:div.grid-empty-placeholder.libs {:data-test "empty-placeholder"}
[:div.text
[:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]]
:else
[:div.grid-empty-placeholder
{:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}}
[:button.create-new {:on-click on-click} (tr "dashboard.new-file")]]))))
(mf/defc loading-placeholder (mf/defc loading-placeholder
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :grid-empty-placeholder :loader)}
(if new-css-system [:div {:class (stl/css :icon)} i/loader]
[:div {:class (stl/css :grid-empty-placeholder :loader)} [:div {:class (stl/css :text)} (tr "dashboard.loading-files")]])
[:div {:class (stl/css :icon)} i/loader]
[:div {:class (stl/css :text)} (tr "dashboard.loading-files")]]
[:div.grid-empty-placeholder.loader
[:div.icon i/loader]
[:div.text (tr "dashboard.loading-files")]])))

View File

@ -18,7 +18,6 @@
[app.main.errors :as errors] [app.main.errors :as errors]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [line-grid]] [app.main.ui.dashboard.grid :refer [line-grid]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]] [app.main.ui.dashboard.project-menu :refer [project-menu]]
@ -37,32 +36,20 @@
(mf/defc header (mf/defc header
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-click (mf/use-fn #(st/emit! (dd/create-project)))]
on-click (mf/use-fn #(st/emit! (dd/create-project)))] [:header {:class (stl/css :dashboard-header)}
(if new-css-system [:div#dashboard-projects-title {:class (stl/css :dashboard-title)}
[:header {:class (stl/css :dashboard-header)} [:h1 (tr "dashboard.projects-title")]]
[:div#dashboard-projects-title {:class (stl/css :dashboard-title)} [:button
[:h1 (tr "dashboard.projects-title")]] {:class (stl/css :btn-secondary :btn-small)
[:button :on-click on-click
{:class (stl/css :btn-secondary :btn-small) :data-test "new-project-button"}
:on-click on-click (tr "dashboard.new-project")]]))
:data-test "new-project-button"}
(tr "dashboard.new-project")]]
;; OLD
[:header.dashboard-header
[:div.dashboard-title#dashboard-projects-title
[:h1 (tr "dashboard.projects-title")]]
[:button.btn-secondary.btn-small
{:on-click on-click
:data-test "new-project-button"}
(tr "dashboard.new-project")]])))
(mf/defc team-hero (mf/defc team-hero
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [team close-fn] :as props}] [{:keys [team close-fn] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members)))
on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members)))
on-invite-click on-invite-click
(mf/use-fn (mf/use-fn
@ -78,52 +65,33 @@
(dom/prevent-default event) (dom/prevent-default event)
(close-fn)))] (close-fn)))]
(if new-css-system [:div {:class (stl/css :team-hero)}
[:div {:class (stl/css :team-hero)} [:div {:class (stl/css :img-wrapper)}
[:div {:class (stl/css :img-wrapper)} [:img {:src "images/deco-team-banner.png"
[:img {:src "images/deco-team-banner.png" :border "0"
:border "0" :role "presentation"}]]
:role "presentation"}]] [:div {:class (stl/css :text)}
[:div {:class (stl/css :text)} [:div {:class (stl/css :title)} (tr "dasboard.team-hero.title")]
[:div {:class (stl/css :title)} (tr "dasboard.team-hero.title")] [:div {:class (stl/css :info)}
[:div {:class (stl/css :info)} [:span (tr "dasboard.team-hero.text")]
[:span (tr "dasboard.team-hero.text")] [:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]
[:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]] [:button
[:button {:class (stl/css :btn-primary :invite)
{:class (stl/css :btn-primary :invite) :on-click on-invite-click}
:on-click on-invite-click} (tr "onboarding.choice.team-up.invite-members")]]
(tr "onboarding.choice.team-up.invite-members")]]
[:button [:button
{:class (stl/css :close) {:class (stl/css :close)
:on-click on-close-click :on-click on-close-click
:aria-label (tr "labels.close")} :aria-label (tr "labels.close")}
[:span i/close]]] [:span i/close]]]))
;; OLD
[:div.team-hero
[:img {:src "images/deco-team-banner.png" :border "0"
:role "presentation"}]
[:div.text
[:div.title (tr "dasboard.team-hero.title")]
[:div.info
[:span (tr "dasboard.team-hero.text")]
[:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]]
[:button.btn-primary.invite
{:on-click on-invite-click}
(tr "onboarding.choice.team-up.invite-members")]
[:button.close
{:on-click on-close-click
:aria-label (tr "labels.close")}
[:span i/close]]])))
(def builtin-templates (def builtin-templates
(l/derived :builtin-templates st/state)) (l/derived :builtin-templates st/state))
(mf/defc tutorial-project (mf/defc tutorial-project
[{:keys [close-tutorial default-project-id] :as props}] [{:keys [close-tutorial default-project-id] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [state (mf/use-state {:status :waiting
state (mf/use-state {:status :waiting
:file nil}) :file nil})
templates (mf/deref builtin-templates) templates (mf/deref builtin-templates)
@ -155,88 +123,51 @@
(swap! state #(assoc % :status :importing)) (swap! state #(assoc % :status :importing))
(st/emit! (with-meta (dd/clone-template (with-meta params mdata)) (st/emit! (with-meta (dd/clone-template (with-meta params mdata))
{::ev/origin "get-started-hero-block"})))))] {::ev/origin "get-started-hero-block"})))))]
(if new-css-system [:article {:class (stl/css :tutorial)}
[:article {:class (stl/css :tutorial)} [:div {:class (stl/css :thumbnail)}]
[:div {:class (stl/css :thumbnail)}] [:div {:class (stl/css :text)}
[:div {:class (stl/css :text)} [:h2 {:class (stl/css :title)} (tr "dasboard.tutorial-hero.title")]
[:h2 {:class (stl/css :title)} (tr "dasboard.tutorial-hero.title")] [:p {:class (stl/css :info)} (tr "dasboard.tutorial-hero.info")]
[:p {:class (stl/css :info)} (tr "dasboard.tutorial-hero.info")] [:button {:class (stl/css :btn-primary :action)
[:button {:class (stl/css :btn-primary :action) :on-click download-tutorial}
:on-click download-tutorial} (case (:status @state)
(case (:status @state) :waiting (tr "dasboard.tutorial-hero.start")
:waiting (tr "dasboard.tutorial-hero.start") :importing [:span.loader i/loader-pencil]
:importing [:span.loader i/loader-pencil] :success "")]]
:success "")]]
[:button [:button
{:class (stl/css :close) {:class (stl/css :close)
:on-click close-tutorial :on-click close-tutorial
:aria-label (tr "labels.close")} :aria-label (tr "labels.close")}
[:span {:class (stl/css :icon)} i/close]]] [:span {:class (stl/css :icon)} i/close]]]))
;; OLD
[:article.tutorial
[:div.thumbnail]
[:div.text
[:h2.title (tr "dasboard.tutorial-hero.title")]
[:p.info (tr "dasboard.tutorial-hero.info")]
[:button.btn-primary.action {:on-click download-tutorial}
(case (:status @state)
:waiting (tr "dasboard.tutorial-hero.start")
:importing [:span.loader i/loader-pencil]
:success "")]]
[:button.close
{:on-click close-tutorial
:aria-label (tr "labels.close")}
[:span.icon i/close]]])))
(mf/defc interface-walkthrough (mf/defc interface-walkthrough
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [close-walkthrough] :as props}] [{:keys [close-walkthrough] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [handle-walkthrough-link
handle-walkthrough-link
(fn [] (fn []
(st/emit! (ptk/event ::ev/event {::ev/name "show-walkthrough" (st/emit! (ptk/event ::ev/event {::ev/name "show-walkthrough"
::ev/origin "get-started-hero-block" ::ev/origin "get-started-hero-block"
:section "dashboard"})))] :section "dashboard"})))]
(if new-css-system [:article {:class (stl/css :walkthrough)}
[:article {:class (stl/css :walkthrough)} [:div {:class (stl/css :thumbnail)}]
[:div {:class (stl/css :thumbnail)}] [:div {:class (stl/css :text)}
[:div {:class (stl/css :text)} [:h2 {:class (stl/css :title)} (tr "dasboard.walkthrough-hero.title")]
[:h2 {:class (stl/css :title)} (tr "dasboard.walkthrough-hero.title")] [:p {:class (stl/css :info)} (tr "dasboard.walkthrough-hero.info")]
[:p {:class (stl/css :info)} (tr "dasboard.walkthrough-hero.info")] [:a {:class (stl/css :btn-primary :action)
[:a {:class (stl/css :btn-primary :action) :href " https://design.penpot.app/walkthrough"
:href " https://design.penpot.app/walkthrough" :target "_blank"
:target "_blank" :on-click handle-walkthrough-link}
:on-click handle-walkthrough-link} (tr "dasboard.walkthrough-hero.start")]]
(tr "dasboard.walkthrough-hero.start")]] [:button
[:button {:class (stl/css :close)
{:class (stl/css :close) :on-click close-walkthrough
:on-click close-walkthrough :aria-label (tr "labels.close")}
:aria-label (tr "labels.close")} [:span {:class (stl/css :icon)} i/close]]]))
[:span {:class (stl/css :icon)} i/close]]]
;; OLD
[:article.walkthrough
[:div.thumbnail]
[:div.text
[:h2.title (tr "dasboard.walkthrough-hero.title")]
[:p.info (tr "dasboard.walkthrough-hero.info")]
[:a.btn-primary.action
{:href " https://design.penpot.app/walkthrough"
:target "_blank"
:on-click handle-walkthrough-link}
(tr "dasboard.walkthrough-hero.start")]]
[:button.close
{:on-click close-walkthrough
:aria-label (tr "labels.close")}
[:span.icon i/close]]])))
(mf/defc project-item (mf/defc project-item
[{:keys [project first? team files] :as props}] [{:keys [project first? team files] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [locale (mf/deref i18n/locale)
locale (mf/deref i18n/locale)
file-count (or (:count project) 0) file-count (or (:count project) 0)
project-id (:id project) project-id (:id project)
team-id (:id team) team-id (:id team)
@ -344,166 +275,85 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(on-menu-click event))))] (on-menu-click event))))]
(if new-css-system [:article {:class (stl/css-case :dashboard-project-row true :first first?)}
[:article {:class (stl/css-case :dashboard-project-row true :first first?)} [:header {:class (stl/css :project)}
[:header {:class (stl/css :project)} [:div {:class (stl/css :project-name-wrapper)}
[:div {:class (stl/css :project-name-wrapper)} (if (:edition? @local)
(if (:edition? @local) [:& inline-edition {:content (:name project)
[:& inline-edition {:content (:name project) :on-end on-edit}]
:on-end on-edit}] [:h2 {:on-click on-nav
[:h2 {:on-click on-nav :on-context-menu on-menu-click}
:on-context-menu on-menu-click} (if (:is-default project)
(if (:is-default project) (tr "labels.drafts")
(tr "labels.drafts") (:name project))])
(:name project))])
[:& project-menu [:& project-menu
{:project project
:show? (:menu-open @local)
:left (+ 24 (:x (:menu-pos @local)))
:top (:y (:menu-pos @local))
:on-edit on-edit-open
:on-menu-close on-menu-close
:on-import on-import}]
[:span {:class (stl/css :info)} (str (tr "labels.num-of-files" (i18n/c file-count)))]
(let [time (-> (:modified-at project)
(dt/timeago {:locale locale}))]
[:span {:class (stl/css :recent-files-row-title-info)} (str ", " time)])
[:div {:class (stl/css :project-actions)}
(when-not (:is-default project)
[:button
{:class (stl/css-case :pin-icon true
:tooltip true
:tooltip-bottom true
:active (:is-pinned project))
:on-click toggle-pin
:alt (tr "dashboard.pin-unpin")
:aria-label (tr "dashboard.pin-unpin")
:tab-index "0"}
(if (:is-pinned project)
i/pin-fill
i/pin)])
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
:on-click on-create-click
:alt (tr "dashboard.new-file")
:aria-label (tr "dashboard.new-file")
:data-test "project-new-file"
:on-key-down handle-create-click}
i/close]
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
:on-click on-menu-click
:alt (tr "dashboard.options")
:aria-label (tr "dashboard.options")
:data-test "project-options"
:on-key-down handle-menu-click}
i/actions]]]]
[:div {:class (stl/css :grid-container) :ref rowref}
[:& line-grid
{:project project
:team team
:files files
:create-fn create-file
:limit limit}]]
(when (and (> limit 0)
(> file-count limit))
[:button
{:class (stl/css :show-more)
:on-click on-nav
:tab-index "0"
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-nav)))}
[:div {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")]
[:div {:class (stl/css :placeholder-icon)} i/arrow-down]])]
;; OLD
[:article.dashboard-project-row
{:class (when first? "first")}
[:header.project {:ref rowref}
[:div.project-name-wrapper
(if (:edition? @local)
[:& inline-edition {:content (:name project)
:on-end on-edit}]
[:h2 {:on-click on-nav
:on-context-menu on-menu-click}
(if (:is-default project)
(tr "labels.drafts")
(:name project))])
[:& project-menu
{:project project
:show? (:menu-open @local)
:left (+ 24 (:x (:menu-pos @local)))
:top (:y (:menu-pos @local))
:on-edit on-edit-open
:on-menu-close on-menu-close
:on-import on-import}]
[:span.info (str (tr "labels.num-of-files" (i18n/c file-count)))]
(let [time (-> (:modified-at project)
(dt/timeago {:locale locale}))]
[:span.recent-files-row-title-info (str ", " time)])
[:div.project-actions
(when-not (:is-default project)
[:button.pin-icon.tooltip.tooltip-bottom
{:class (when (:is-pinned project) "active")
:on-click toggle-pin
:alt (tr "dashboard.pin-unpin")
:aria-label (tr "dashboard.pin-unpin")
:tab-index "0"}
(if (:is-pinned project)
i/pin-fill
i/pin)])
[:button.btn-secondary.btn-small.tooltip.tooltip-bottom
{:on-click on-create-click
:alt (tr "dashboard.new-file")
:aria-label (tr "dashboard.new-file")
:data-test "project-new-file"
:tab-index "0"
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-create-click event)))}
i/close]
[:button.btn-secondary.btn-small.tooltip.tooltip-bottom
{:on-click on-menu-click
:alt (tr "dashboard.options")
:aria-label (tr "dashboard.options")
:data-test "project-options"
:tab-index "0"
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions]]]]
[:& line-grid
{:project project {:project project
:team team :show? (:menu-open @local)
:files files :left (+ 24 (:x (:menu-pos @local)))
:create-fn create-file :top (:y (:menu-pos @local))
:limit limit}] :on-edit on-edit-open
:on-menu-close on-menu-close
:on-import on-import}]
(when (and (> limit 0) [:span {:class (stl/css :info)} (str (tr "labels.num-of-files" (i18n/c file-count)))]
(> file-count limit))
[:button.show-more {:on-click on-nav (let [time (-> (:modified-at project)
:tab-index "0" (dt/timeago {:locale locale}))]
:on-key-down (fn [event] [:span {:class (stl/css :recent-files-row-title-info)} (str ", " time)])
(when (kbd/enter? event)
(on-nav)))} [:div {:class (stl/css :project-actions)}
[:div.placeholder-label (when-not (:is-default project)
(tr "dashboard.show-all-files")] [:button
[:div.placeholder-icon i/arrow-down]])]))) {:class (stl/css-case :pin-icon true
:tooltip true
:tooltip-bottom true
:active (:is-pinned project))
:on-click toggle-pin
:alt (tr "dashboard.pin-unpin")
:aria-label (tr "dashboard.pin-unpin")
:tab-index "0"}
(if (:is-pinned project)
i/pin-fill
i/pin)])
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
:on-click on-create-click
:alt (tr "dashboard.new-file")
:aria-label (tr "dashboard.new-file")
:data-test "project-new-file"
:on-key-down handle-create-click}
i/close]
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
:on-click on-menu-click
:alt (tr "dashboard.options")
:aria-label (tr "dashboard.options")
:data-test "project-options"
:on-key-down handle-menu-click}
i/actions]]]]
[:div {:class (stl/css :grid-container) :ref rowref}
[:& line-grid
{:project project
:team team
:files files
:create-fn create-file
:limit limit}]]
(when (and (> limit 0)
(> file-count limit))
[:button
{:class (stl/css :show-more)
:on-click on-nav
:tab-index "0"
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-nav)))}
[:div {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")]
[:div {:class (stl/css :placeholder-icon)} i/arrow-down]])]))
(def recent-files-ref (def recent-files-ref
@ -511,8 +361,7 @@
(mf/defc projects-section (mf/defc projects-section
[{:keys [team projects profile default-project-id] :as props}] [{:keys [team projects profile default-project-id] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [projects (->> (vals projects)
projects (->> (vals projects)
(sort-by :modified-at) (sort-by :modified-at)
(reverse)) (reverse))
recent-map (mf/deref recent-files-ref) recent-map (mf/deref recent-files-ref)
@ -562,68 +411,34 @@
(st/emit! (dd/fetch-recent-files team-id) (st/emit! (dd/fetch-recent-files team-id)
(dd/clear-selected-files))) (dd/clear-selected-files)))
(if new-css-system (when (seq projects)
(when (seq projects) [:*
[:* [:& header]
[:& header]
(when team-hero? (when team-hero?
[:& team-hero {:team team :close-fn close-banner}]) [:& team-hero {:team team :close-fn close-banner}])
(when (and (contains? cf/flags :dashboard-templates-section) (when (and (contains? cf/flags :dashboard-templates-section)
(or (not tutorial-viewed?) (or (not tutorial-viewed?)
(not walkthrough-viewed?))) (not walkthrough-viewed?)))
[:div {:class (stl/css :hero-projects)} [:div {:class (stl/css :hero-projects)}
(when (and (not tutorial-viewed?) (:is-default team)) (when (and (not tutorial-viewed?) (:is-default team))
[:& tutorial-project [:& tutorial-project
{:close-tutorial close-tutorial {:close-tutorial close-tutorial
:default-project-id default-project-id}]) :default-project-id default-project-id}])
(when (and (not walkthrough-viewed?) (:is-default team)) (when (and (not walkthrough-viewed?) (:is-default team))
[:& interface-walkthrough [:& interface-walkthrough
{:close-walkthrough close-walkthrough}])]) {:close-walkthrough close-walkthrough}])])
[:div {:class (stl/css :dashboard-container :no-bg :dashboard-projects)} [:div {:class (stl/css :dashboard-container :no-bg :dashboard-projects)}
(for [{:keys [id] :as project} projects] (for [{:keys [id] :as project} projects]
(let [files (when recent-map (let [files (when recent-map
(->> (vals recent-map) (->> (vals recent-map)
(filterv #(= id (:project-id %))) (filterv #(= id (:project-id %)))
(sort-by :modified-at #(compare %2 %1))))] (sort-by :modified-at #(compare %2 %1))))]
[:& project-item {:project project [:& project-item {:project project
:team team :team team
:files files :files files
:first? (= project (first projects)) :first? (= project (first projects))
:key id}]))]]) :key id}]))]])))
;; OLD
(when (seq projects)
[:*
[:& header]
(when team-hero?
[:& team-hero {:team team :close-fn close-banner}])
(when (and (contains? cf/flags :dashboard-templates-section)
(or (not tutorial-viewed?)
(not walkthrough-viewed?)))
[:div.hero-projects
(when (and (not tutorial-viewed?) (:is-default team))
[:& tutorial-project
{:close-tutorial close-tutorial
:default-project-id default-project-id}])
(when (and (not walkthrough-viewed?) (:is-default team))
[:& interface-walkthrough
{:close-walkthrough close-walkthrough}])])
[:div.dashboard-container.no-bg.dashboard-projects
(for [{:keys [id] :as project} projects]
(let [files (when recent-map
(->> (vals recent-map)
(filterv #(= id (:project-id %)))
(sort-by :modified-at #(compare %2 %1))))]
[:& project-item {:project project
:team team
:files files
:first? (= project (first projects))
:key id}]))]]))))

View File

@ -10,7 +10,6 @@
[app.main.data.dashboard :as dd] [app.main.data.dashboard :as dd]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.grid :refer [grid]] [app.main.ui.dashboard.grid :refer [grid]]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
@ -20,8 +19,7 @@
(mf/defc search-page (mf/defc search-page
[{:keys [team search-term] :as props}] [{:keys [team search-term] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [result (mf/deref refs/dashboard-search-result)
result (mf/deref refs/dashboard-search-result)
[rowref limit] (hooks/use-dynamic-grid-item-width)] [rowref limit] (hooks/use-dynamic-grid-item-width)]
(mf/use-effect (mf/use-effect
@ -38,61 +36,31 @@
(fn [] (fn []
(st/emit! (dd/search {:search-term search-term}) (st/emit! (dd/search {:search-term search-term})
(dd/clear-selected-files)))) (dd/clear-selected-files))))
(if new-css-system [:*
[:* [:header {:class (stl/css :dashboard-header)}
[:header {:class (stl/css :dashboard-header)} [:div#dashboard-search-title {:class (stl/css :dashboard-title)}
[:div#dashboard-search-title {:class (stl/css :dashboard-title)} [:h1 (tr "dashboard.title-search")]]]
[:h1 (tr "dashboard.title-search")]]]
[:section {:class (stl/css :dashboard-container :search :no-bg) [:section {:class (stl/css :dashboard-container :search :no-bg)
:ref rowref} :ref rowref}
(cond (cond
(empty? search-term) (empty? search-term)
[:div {:class (stl/css :grid-empty-placeholder :search)} [:div {:class (stl/css :grid-empty-placeholder :search)}
[:div {:class (stl/css :icon)} i/search] [:div {:class (stl/css :icon)} i/search]
[:div {:class (stl/css :text)} (tr "dashboard.type-something")]] [:div {:class (stl/css :text)} (tr "dashboard.type-something")]]
(nil? result) (nil? result)
[:div {:class (stl/css :grid-empty-placeholder :search)} [:div {:class (stl/css :grid-empty-placeholder :search)}
[:div {:class (stl/css :icon)} i/search] [:div {:class (stl/css :icon)} i/search]
[:div {:class (stl/css :text)} (tr "dashboard.searching-for" search-term)]] [:div {:class (stl/css :text)} (tr "dashboard.searching-for" search-term)]]
(empty? result) (empty? result)
[:div {:class (stl/css :grid-empty-placeholder :search)} [:div {:class (stl/css :grid-empty-placeholder :search)}
[:div {:class (stl/css :icon)} i/search] [:div {:class (stl/css :icon)} i/search]
[:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]] [:div {:class (stl/css :text)} (tr "dashboard.no-matches-for" search-term)]]
:else :else
[:& grid {:files result [:& grid {:files result
:hide-new? true :hide-new? true
:origin :search :origin :search
:limit limit}])]] :limit limit}])]]))
;; OLD
[:*
[:header.dashboard-header
[:div.dashboard-title#dashboard-search-title
[:h1 (tr "dashboard.title-search")]]]
[:section.dashboard-container.search.no-bg {:ref rowref}
(cond
(empty? search-term)
[:div.grid-empty-placeholder.search
[:div.icon i/search]
[:div.text (tr "dashboard.type-something")]]
(nil? result)
[:div.grid-empty-placeholder.search
[:div.icon i/search]
[:div.text (tr "dashboard.searching-for" search-term)]]
(empty? result)
[:div.grid-empty-placeholder.search
[:div.icon i/search]
[:div.text (tr "dashboard.no-matches-for" search-term)]]
:else
[:& grid {:files result
:hide-new? true
:origin :search
:limit limit}])]])))

View File

@ -20,7 +20,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]] [app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
[app.main.ui.components.link :refer [link]] [app.main.ui.components.link :refer [link]]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.comments :refer [comments-icon comments-section]] [app.main.ui.dashboard.comments :refer [comments-icon comments-section]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.project-menu :refer [project-menu]] [app.main.ui.dashboard.project-menu :refer [project-menu]]
@ -41,8 +40,7 @@
(mf/defc sidebar-project (mf/defc sidebar-project
[{:keys [item selected?] :as props}] [{:keys [item selected?] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [dstate (mf/deref refs/dashboard-local)
dstate (mf/deref refs/dashboard-local)
selected-files (:selected-files dstate) selected-files (:selected-files dstate)
selected-project (:selected-project dstate) selected-project (:selected-project dstate)
edit-id (:project-for-edit dstate) edit-id (:project-for-edit dstate)
@ -136,59 +134,33 @@
mdata {:on-success on-drop-success}] mdata {:on-success on-drop-success}]
(st/emit! (dd/move-files (with-meta data mdata)))))))] (st/emit! (dd/move-files (with-meta data mdata)))))))]
(if new-css-system [:*
[:* [:li {:tab-index "0"
[:li {:tab-index "0" :class (stl/css-case :project-element true
:class (stl/css-case :project-element true :current selected?
:current selected? :dragging (:dragging? local))
:dragging (:dragging? local)) :on-click on-click
:on-click on-click :on-key-down on-key-down
:on-key-down on-key-down :on-double-click on-edit-open
:on-double-click on-edit-open :on-context-menu on-menu-click
:on-context-menu on-menu-click :on-drag-enter on-drag-enter
:on-drag-enter on-drag-enter :on-drag-over on-drag-over
:on-drag-over on-drag-over :on-drag-leave on-drag-leave
:on-drag-leave on-drag-leave :on-drop on-drop}
:on-drop on-drop} (if (:edition? local)
(if (:edition? local) [:& inline-edition {:content (:name item)
[:& inline-edition {:content (:name item) :on-end on-edit}]
:on-end on-edit}] [:span {:class (stl/css :element-title)} (:name item)])]
[:span {:class (stl/css :element-title)} (:name item)])] [:& project-menu {:project item
[:& project-menu {:project item :show? (:menu-open local)
:show? (:menu-open local) :left (:x (:menu-pos local))
:left (:x (:menu-pos local)) :top (:y (:menu-pos local))
:top (:y (:menu-pos local)) :on-edit on-edit-open
:on-edit on-edit-open :on-menu-close on-menu-close}]]))
:on-menu-close on-menu-close}]]
;; OLD
[:*
[:li {:tab-index "0"
:class (if selected? "current"
(when (:dragging? local) "dragging"))
:on-click on-click
:on-key-down on-key-down
:on-double-click on-edit-open
:on-context-menu on-menu-click
:on-drag-enter on-drag-enter
:on-drag-over on-drag-over
:on-drag-leave on-drag-leave
:on-drop on-drop}
(if (:edition? local)
[:& inline-edition {:content (:name item)
:on-end on-edit}]
[:span.element-title (:name item)])]
[:& project-menu {:project item
:show? (:menu-open local)
:left (:x (:menu-pos local))
:top (:y (:menu-pos local))
:on-edit on-edit-open
:on-menu-close on-menu-close}]])))
(mf/defc sidebar-search (mf/defc sidebar-search
[{:keys [search-term team-id] :as props}] [{:keys [search-term team-id] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [search-term (or search-term "")
search-term (or search-term "")
focused? (mf/use-state false) focused? (mf/use-state false)
emit! (mf/use-memo #(f/debounce st/emit! 500)) emit! (mf/use-memo #(f/debounce st/emit! 500))
@ -236,70 +208,39 @@
(when (kbd/enter? event) (when (kbd/enter? event)
(on-clear-click event))))] (on-clear-click event))))]
(if new-css-system [:form {:class (stl/css :sidebar-search)}
[:form {:class (stl/css :sidebar-search)} [:input
[:input {:class (stl/css :input-text)
{:class (stl/css :input-text) :key "images-search-box"
:key "images-search-box" :id "search-input"
:id "search-input" :type "text"
:type "text" :aria-label (tr "dashboard.search-placeholder")
:aria-label (tr "dashboard.search-placeholder") :placeholder (tr "dashboard.search-placeholder")
:placeholder (tr "dashboard.search-placeholder") :default-value search-term
:default-value search-term :auto-complete "off"
:auto-complete "off" ;; :on-focus on-search-focus
;; :on-focus on-search-focus :on-blur on-search-blur
:on-blur on-search-blur :on-change on-search-change
:on-change on-search-change :on-key-press on-key-press
:on-key-press on-key-press :ref #(when % (set! (.-value %) search-term))}]
:ref #(when % (set! (.-value %) search-term))}]
(if (or @focused? (seq search-term)) (if (or @focused? (seq search-term))
[:div [:div
{:class (stl/css :clear-search) {:class (stl/css :clear-search)
:tab-index "0" :tab-index "0"
:on-click on-clear-click :on-click on-clear-click
:on-key-down handle-clear-search} :on-key-down handle-clear-search}
i/close] i/close]
[:div [:div
{:class (stl/css :search) {:class (stl/css :search)
:on-click on-clear-click} :on-click on-clear-click}
i/search])] i/search])]))
;; OLD
[:form.sidebar-search
[:input.input-text
{:key "images-search-box"
:id "search-input"
:type "text"
:aria-label (tr "dashboard.search-placeholder")
:placeholder (tr "dashboard.search-placeholder")
:default-value search-term
:auto-complete "off"
;; :on-focus on-search-focus
:on-blur on-search-blur
:on-change on-search-change
:on-key-press on-key-press
:ref #(when % (set! (.-value %) search-term))}]
(if (or @focused? (seq search-term))
[:div.clear-search
{:tab-index "0"
:on-click on-clear-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-clear-click event)))}
i/close]
[:div.search
{:on-click on-clear-click}
i/search])])))
(mf/defc teams-selector-dropdown-items (mf/defc teams-selector-dropdown-items
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [team profile teams] :as props}] [{:keys [team profile teams] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-create-clicked
on-create-clicked
(mf/use-callback (mf/use-callback
#(st/emit! (modal/show :team-form {}))) #(st/emit! (modal/show :team-form {})))
@ -318,76 +259,38 @@
(when (kbd/enter? event) (when (kbd/enter? event)
(team-selected id event)))] (team-selected id event)))]
(if new-css-system [:*
[:* [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
[:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile)) :on-key-down handle-select-default
:on-key-down handle-select-default :id "teams-selector-default-team"
:id "teams-selector-default-team" :class (stl/css :team-name)}
:class (stl/css :team-name)} [:span {:class (stl/css :team-icon)} i/logo-icon]
[:span {:class (stl/css :team-icon)} i/logo-icon] [:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")]
[:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")] (when (= (:default-team-id profile) (:id team))
(when (= (:default-team-id profile) (:id team)) [:span {:class (stl/css :icon)} i/tick])]
[:span {:class (stl/css :icon)} i/tick])]
(for [team-item (remove :is-default (vals teams))] (for [team-item (remove :is-default (vals teams))]
[:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item)) [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
:on-key-down (partial handle-select-team (:id team-item)) :on-key-down (partial handle-select-team (:id team-item))
:id (str "teams-selector-" (:id team-item)) :id (str "teams-selector-" (:id team-item))
:class (stl/css :team-name) :class (stl/css :team-name)
:key (str "teams-selector-" (:id team-item))} :key (str "teams-selector-" (:id team-item))}
[:span {:class (stl/css :team-icon)} [:span {:class (stl/css :team-icon)}
[:img {:src (cf/resolve-team-photo-url team-item) [:img {:src (cf/resolve-team-photo-url team-item)
:alt (:name team-item)}]] :alt (:name team-item)}]]
[:span {:class (stl/css :team-text) [:span {:class (stl/css :team-text)
:title (:name team-item)} (:name team-item)] :title (:name team-item)} (:name team-item)]
(when (= (:id team-item) (:id team)) (when (= (:id team-item) (:id team))
[:span {:class (stl/css :icon)} i/tick])]) [:span {:class (stl/css :icon)} i/tick])])
[:hr {:role "separator"}] [:hr {:role "separator"}]
[:> dropdown-menu-item* {:on-click on-create-clicked [:> dropdown-menu-item* {:on-click on-create-clicked
:on-key-down (fn [event] :on-key-down (fn [event]
(when (kbd/enter? event) (when (kbd/enter? event)
(on-create-clicked event))) (on-create-clicked event)))
:id "teams-selector-create-team" :id "teams-selector-create-team"
:class (stl/css :team-name :action)} :class (stl/css :team-name :action)}
[:span {:class (stl/css :team-icon :new-team)} i/close] [:span {:class (stl/css :team-icon :new-team)} i/close]
[:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]] [:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]]))
;; OLD
[:*
[:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
:on-key-down (fn [event]
(when (kbd/enter? event)
(team-selected (:default-team-id profile) event)))
:id "teams-selector-default-team"
:class "team-name"}
[:span.team-icon i/logo-icon]
[:span.team-text (tr "dashboard.your-penpot")]
(when (= (:default-team-id profile) (:id team))
[:span.icon i/tick])]
(for [team-item (remove :is-default (vals teams))]
[:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
:on-key-down (fn [event]
(when (kbd/enter? event)
(team-selected (:id team-item) event)))
:id (str "teams-selector-" (:id team-item))
:class "team-name"
:key (str "teams-selector-" (:id team-item))}
[:span.team-icon
[:img {:src (cf/resolve-team-photo-url team-item)
:alt (:name team-item)}]]
[:span.team-text {:title (:name team-item)} (:name team-item)]
(when (= (:id team-item) (:id team))
[:span.icon i/tick])])
[:hr {:role "separator"}]
[:> dropdown-menu-item* {:on-click on-create-clicked
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-create-clicked event)))
:id "teams-selector-create-team"
:class "team-name action"}
[:span.team-icon.new-team i/close]
[:span.team-text (tr "dashboard.create-new-team")]]])))
(s/def ::member-id ::us/uuid) (s/def ::member-id ::us/uuid)
(s/def ::leave-modal-form (s/def ::leave-modal-form
@ -395,8 +298,7 @@
(mf/defc team-options-dropdown (mf/defc team-options-dropdown
[{:keys [team profile] :as props}] [{:keys [team profile] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [go-members #(st/emit! (dd/go-to-team-members))
go-members #(st/emit! (dd/go-to-team-members))
go-invitations #(st/emit! (dd/go-to-team-invitations)) go-invitations #(st/emit! (dd/go-to-team-invitations))
go-webhooks #(st/emit! (dd/go-to-team-webhooks)) go-webhooks #(st/emit! (dd/go-to-team-webhooks))
go-settings #(st/emit! (dd/go-to-team-settings)) go-settings #(st/emit! (dd/go-to-team-settings))
@ -549,15 +451,13 @@
(when (kbd/enter? event) (when (kbd/enter? event)
(on-delete-clicked))) (on-delete-clicked)))
:id "teams-options-delete-team" :id "teams-options-delete-team"
:class (if new-css-system (stl/css :warning) "warning") :class (stl/css :warning)
:data-test "delete-team"} :data-test "delete-team"}
(tr "dashboard.delete-team")])])) (tr "dashboard.delete-team")])]))
(mf/defc sidebar-team-switch (mf/defc sidebar-team-switch
[{:keys [team profile] :as props}] [{:keys [team profile] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [teams (mf/deref refs/teams)
teams (mf/deref refs/teams)
teams-without-default (into {} (filter (fn [[_ v]] (= false (:is-default v))) teams)) teams-without-default (into {} (filter (fn [[_ v]] (= false (:is-default v))) teams))
team-ids (map #(str "teams-selector-" %) (keys teams-without-default)) team-ids (map #(str "teams-selector-" %) (keys teams-without-default))
ids (concat ["teams-selector-default-team"] team-ids ["teams-selector-create-team"]) ids (concat ["teams-selector-default-team"] team-ids ["teams-selector-create-team"])
@ -615,119 +515,55 @@
(fn [] (fn []
(reset! show-teams-ddwn? false))] (reset! show-teams-ddwn? false))]
(if new-css-system [:div {:class (stl/css :sidebar-team-switch)}
[:div {:class (stl/css :sidebar-team-switch)} [:div {:class (stl/css :switch-content)}
[:div {:class (stl/css :switch-content)} [:button
{:class (stl/css :current-team)
:tab-index "0"
:on-click handle-show-team-click
:on-key-down handle-show-team-keydown}
(if (:is-default team)
[:div {:class (stl/css :team-name)}
[:span {:class (stl/css :team-icon)} i/logo-icon]
[:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]]
[:div {:class (stl/css :team-name)}
[:span {:class (stl/css :team-icon)}
[:img {:src (cf/resolve-team-photo-url team)
:alt (:name team)}]]
[:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
[:span {:class (stl/css :switch-icon)} i/arrow-down]]
(when-not (:is-default team)
[:button [:button
{:class (stl/css :current-team) {:class (stl/css :switch-options)
:on-click handle-show-opts-click
:tab-index "0" :tab-index "0"
:on-click handle-show-team-click :on-key-down handle-show-opts-keydown}
:on-key-down handle-show-team-keydown} i/actions])]
;; Teams Dropdown
[:& dropdown-menu {:show @show-teams-ddwn?
:on-close handle-close-team
:ids ids
:list-class (stl/css :dropdown :teams-dropdown)}
[:& teams-selector-dropdown-items {:ids ids
:team team
:profile profile
:teams teams}]]
(if (:is-default team) [:& dropdown-menu {:show @show-team-opts-ddwn?
[:div {:class (stl/css :team-name)} :on-close #(reset! show-team-opts-ddwn? false)
[:span {:class (stl/css :team-icon)} i/logo-icon] :ids options-ids
[:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]] :list-class (stl/css :dropdown :options-dropdown)}
[:div {:class (stl/css :team-name)} [:& team-options-dropdown {:team team
[:span {:class (stl/css :team-icon)} :profile profile}]]]))
[:img {:src (cf/resolve-team-photo-url team)
:alt (:name team)}]]
[:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
[:span {:class (stl/css :switch-icon)} i/arrow-down]]
(when-not (:is-default team)
[:button
{:class (stl/css :switch-options)
:on-click handle-show-opts-click
:tab-index "0"
:on-key-down handle-show-opts-keydown}
i/actions])]
;; Teams Dropdown
[:& dropdown-menu {:show @show-teams-ddwn?
:on-close handle-close-team
:ids ids
:list-class (stl/css :dropdown :teams-dropdown)}
[:& teams-selector-dropdown-items {:ids ids
:team team
:profile profile
:teams teams}]]
[:& dropdown-menu {:show @show-team-opts-ddwn?
:on-close #(reset! show-team-opts-ddwn? false)
:ids options-ids
:list-class (stl/css :dropdown :options-dropdown)}
[:& team-options-dropdown {:team team
:profile profile}]]]
;; Old css
[:div.sidebar-team-switch
[:div.switch-content
[:button.current-team {:tab-index "0"
:on-click (fn [event]
(dom/stop-propagation event)
(reset! show-teams-ddwn? true))
:on-key-down (fn [event]
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-teams-ddwn? true)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first ids))]
(when first-element
(dom/focus! first-element)))))))}
(if (:is-default team)
[:div.team-name
[:span.team-icon i/logo-icon]
[:span.team-text (tr "dashboard.default-team-name")]]
[:div.team-name
[:span.team-icon
[:img {:src (cf/resolve-team-photo-url team)
:alt (:name team)}]]
[:span.team-text {:title (:name team)} (:name team)]])
[:span.switch-icon
i/arrow-down]]
(when-not (:is-default team)
[:button.switch-options {:on-click (fn [event]
(dom/stop-propagation event)
(reset! show-team-opts-ddwn? true))
:tab-index "0"
:on-key-down (fn [event]
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-team-opts-ddwn? true)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first options-ids))]
(when first-element
(dom/focus! first-element)))))))}
i/actions])]
;; Teams Dropdown
[:& dropdown-menu {:show @show-teams-ddwn?
:on-close #(reset! show-teams-ddwn? false)
:ids ids
:list-class "dropdown teams-dropdown"}
[:& teams-selector-dropdown-items {:ids ids
:team team
:profile profile
:teams teams}]]
[:& dropdown-menu {:show @show-team-opts-ddwn?
:on-close #(reset! show-team-opts-ddwn? false)
:ids options-ids
:list-class "dropdown options-dropdown"}
[:& team-options-dropdown {:team team
:profile profile}]]])))
(mf/defc sidebar-content (mf/defc sidebar-content
[{:keys [projects profile section team project search-term] :as props}] [{:keys [projects profile section team project search-term] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [default-project-id
default-project-id
(->> (vals projects) (->> (vals projects)
(d/seek :is-default) (d/seek :is-default)
(:id)) (:id))
@ -813,115 +649,61 @@
(remove :is-default) (remove :is-default)
(filter :is-pinned))] (filter :is-pinned))]
(if new-css-system [:div {:class (stl/css :sidebar-content)}
[:div {:class (stl/css :sidebar-content)} [:& sidebar-team-switch {:team team :profile profile}]
[:& sidebar-team-switch {:team team :profile profile}] [:hr]
[:hr] [:& sidebar-search {:search-term search-term
[:& sidebar-search {:search-term search-term :team-id (:id team)}]
:team-id (:id team)}]
[:div {:class (stl/css :sidebar-content-section)} [:div {:class (stl/css :sidebar-content-section)}
[:ul {:class (stl/css :sidebar-nav :no-overflow)} [:ul {:class (stl/css :sidebar-nav :no-overflow)}
[:li [:li
{:class (stl/css :recent-projects) {:class (stl/css :recent-projects)
:class-name (when projects? (stl/css :current))} :class-name (when projects? (stl/css :current))}
[:& link {:action go-projects [:& link {:action go-projects
:keyboard-action go-projects-with-key} :keyboard-action go-projects-with-key}
[:span {:class (stl/css :element-title)} (tr "labels.projects")]]] [:span {:class (stl/css :element-title)} (tr "labels.projects")]]]
[:li {:class-name (when drafts? (stl/css :current))} [:li {:class-name (when drafts? (stl/css :current))}
[:& link {:action go-drafts [:& link {:action go-drafts
:keyboard-action go-drafts-with-key} :keyboard-action go-drafts-with-key}
[:span {:class (stl/css :element-title)} (tr "labels.drafts")]]] [:span {:class (stl/css :element-title)} (tr "labels.drafts")]]]
[:li {:class-name (when libs? (stl/css :current))} [:li {:class-name (when libs? (stl/css :current))}
[:& link {:action go-libs [:& link {:action go-libs
:keyboard-action go-libs-with-key} :keyboard-action go-libs-with-key}
[:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]] [:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]]
[:hr] [:hr]
[:div {:class (stl/css :sidebar-content-section)} [:div {:class (stl/css :sidebar-content-section)}
[:ul {:class (stl/css :sidebar-nav :no-overflow)} [:ul {:class (stl/css :sidebar-nav :no-overflow)}
[:li {:class-name (when fonts? (stl/css :current))} [:li {:class-name (when fonts? (stl/css :current))}
[:& link {:action go-fonts [:& link {:action go-fonts
:keyboard-action go-fonts-with-key :keyboard-action go-fonts-with-key
:data-test "fonts"} :data-test "fonts"}
[:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]] [:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]]
[:hr]
[:div {:class (stl/css :sidebar-content-section)
:data-test "pinned-projects"}
(if (seq pinned-projects)
[:ul {:class (stl/css :sidebar-nav)}
(for [item pinned-projects]
[:& sidebar-project
{:item item
:key (dm/str (:id item))
:id (:id item)
:team-id (:id team)
:selected? (= (:id item) (:id project))}])]
[:div {:class (stl/css :sidebar-empty-placeholder)}
[:span {:class (stl/css :icon)} i/pin]
[:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]]
;; OLD STYLES
[:div.sidebar-content
[:& sidebar-team-switch {:team team :profile profile}]
[:hr]
[:& sidebar-search {:search-term search-term
:team-id (:id team)}]
[:div.sidebar-content-section
[:ul.sidebar-nav.no-overflow
[:li.recent-projects
{:class-name (when projects? "current")}
[:& link {:action go-projects
:keyboard-action go-projects-with-key}
[:span.element-title (tr "labels.projects")]]]
[:li {:class-name (when drafts? "current")}
[:& link {:action go-drafts
:keyboard-action go-drafts-with-key}
[:span.element-title (tr "labels.drafts")]]]
[:li {:class-name (when libs? "current")}
[:& link {:action go-libs
:keyboard-action go-libs-with-key}
[:span.element-title (tr "labels.shared-libraries")]]]]]
[:hr]
[:div.sidebar-content-section
[:ul.sidebar-nav.no-overflow
[:li {:class-name (when fonts? "current")}
[:& link {:action go-fonts
:keyboard-action go-fonts-with-key
:data-test "fonts"}
[:span.element-title (tr "labels.fonts")]]]]]
[:hr]
[:div.sidebar-content-section {:data-test "pinned-projects"}
(if (seq pinned-projects)
[:ul.sidebar-nav
(for [item pinned-projects]
[:& sidebar-project
{:item item
:key (dm/str (:id item))
:id (:id item)
:team-id (:id team)
:selected? (= (:id item) (:id project))}])]
[:div.sidebar-empty-placeholder
[:span.icon i/pin]
[:span.text (tr "dashboard.no-projects-placeholder")]])]])))
[:hr]
[:div {:class (stl/css :sidebar-content-section)
:data-test "pinned-projects"}
(if (seq pinned-projects)
[:ul {:class (stl/css :sidebar-nav)}
(for [item pinned-projects]
[:& sidebar-project
{:item item
:key (dm/str (:id item))
:id (:id item)
:team-id (:id team)
:selected? (= (:id item) (:id project))}])]
[:div {:class (stl/css :sidebar-empty-placeholder)}
[:span {:class (stl/css :icon)} i/pin]
[:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]]))
(mf/defc profile-section (mf/defc profile-section
[{:keys [profile team] :as props}] [{:keys [profile team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [show (mf/use-state false)
show (mf/use-state false)
photo (cf/resolve-profile-photo-url profile) photo (cf/resolve-profile-photo-url profile)
on-click on-click
@ -1024,236 +806,110 @@
(fn [event] (fn [event]
(when (kbd/enter? event) (when (kbd/enter? event)
(on-click (du/logout) event))))] (on-click (du/logout) event))))]
(if new-css-system
[:*
(when (and team profile)
[:& comments-section
{:profile profile
:team team
:show? show-comments?
:on-show-comments handle-show-comments
:on-hide-comments handle-hide-comments}])
[:div {:class (stl/css :profile-section)} [:*
[:div {:class (stl/css :profile) (when (and team profile)
:tab-index "0" [:& comments-section
:on-click handle-click {:profile profile
:on-key-down handle-key-down :team team
:data-test "profile-btn"} :show? show-comments?
[:img {:src photo :on-show-comments handle-show-comments
:alt (:fullname profile)}] :on-hide-comments handle-hide-comments}])
[:span (:fullname profile)]]
[:& dropdown-menu {:on-close handle-close :show @show} [:div {:class (stl/css :profile-section)}
[:ul {:class (stl/css :dropdown)} [:div {:class (stl/css :profile)
[:li {:tab-index (if @show "0" "-1") :tab-index "0"
:on-click (partial on-click :settings-profile) :on-click handle-click
:on-key-down handle-key-down-profile :on-key-down handle-key-down
:data-test "profile-profile-opt"} :data-test "profile-btn"}
[:span {:class (stl/css :text)} (tr "labels.your-account")]] [:img {:src photo
:alt (:fullname profile)}]
[:span (:fullname profile)]]
[:& dropdown-menu {:on-close handle-close :show @show}
[:ul {:class (stl/css :dropdown)}
[:li {:tab-index (if @show "0" "-1")
:on-click (partial on-click :settings-profile)
:on-key-down handle-key-down-profile
:data-test "profile-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.your-account")]]
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
:data-url "https://help.penpot.app"
:on-click handle-click-url
:on-key-down handle-keydown-url
:data-test "help-center-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.help-center")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://community.penpot.app"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "labels.community")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://www.youtube.com/c/Penpot"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "labels.tutorials")]]
[:li {:tab-index (if @show "0" "-1")
:on-click show-release-notes
:on-key-down handle-show-release-notes}
[:span {:class (stl/css :text)} (tr "labels.release-notes")]]
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
:data-url "https://penpot.app/libraries-templates"
:on-click handle-click-url
:on-key-down handle-keydown-url
:data-test "libraries-templates-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://github.com/penpot/penpot"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "labels.github-repo")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://penpot.app/terms"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
(when (contains? cf/flags :user-feedback)
[:li {:class (stl/css :separator) [:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1") :tab-index (if @show "0" "-1")
:data-url "https://help.penpot.app" :on-click handle-feedback-click
:on-click handle-click-url :on-key-down handle-feedback-keydown
:on-key-down handle-keydown-url :data-test "feedback-profile-opt"}
:data-test "help-center-profile-opt"} [:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
[:span {:class (stl/css :text)} (tr "labels.help-center")]]
[:li {:tab-index (if @show "0" "-1") [:li {:class (stl/css :separator)
:data-url "https://community.penpot.app" :tab-index (if @show "0" "-1")
:on-click handle-click-url :on-click handle-logout-click
:on-key-down handle-keydown-url} :on-key-down handle-logout-keydown
[:span {:class (stl/css :text)} (tr "labels.community")]] :data-test "logout-profile-opt"}
[:span {:class (stl/css :icon)} i/exit]
[:span {:class (stl/css :text)} (tr "labels.logout")]]]]
[:li {:tab-index (if @show "0" "-1") (when (and team profile)
:data-url "https://www.youtube.com/c/Penpot" [:& comments-icon
:on-click handle-click-url {:profile profile
:on-key-down handle-keydown-url} :show? show-comments?
[:span {:class (stl/css :text)} (tr "labels.tutorials")]] :on-show-comments handle-show-comments}])]]))
[:li {:tab-index (if @show "0" "-1")
:on-click show-release-notes
:on-key-down handle-show-release-notes}
[:span {:class (stl/css :text)} (tr "labels.release-notes")]]
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
:data-url "https://penpot.app/libraries-templates"
:on-click handle-click-url
:on-key-down handle-keydown-url
:data-test "libraries-templates-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://github.com/penpot/penpot"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "labels.github-repo")]]
[:li {:tab-index (if @show "0" "-1")
:data-url "https://penpot.app/terms"
:on-click handle-click-url
:on-key-down handle-keydown-url}
[:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
(when (contains? cf/flags :user-feedback)
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
:on-click handle-feedback-click
:on-key-down handle-feedback-keydown
:data-test "feedback-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
[:li {:class (stl/css :separator)
:tab-index (if @show "0" "-1")
:on-click handle-logout-click
:on-key-down handle-logout-keydown
:data-test "logout-profile-opt"}
[:span {:class (stl/css :icon)} i/exit]
[:span {:class (stl/css :text)} (tr "labels.logout")]]]]
(when (and team profile)
[:& comments-icon
{:profile profile
:show? show-comments?
:on-show-comments handle-show-comments}])]]
;; OLD
[:div.profile-section
[:div.profile {:tab-index "0"
:on-click (fn [event]
(dom/stop-propagation event)
(reset! show true))
:on-key-down (fn [event]
(when (kbd/enter? event)
(reset! show true)))
:data-test "profile-btn"}
[:img {:src photo
:alt (:fullname profile)}]
[:span (:fullname profile)]]
[:& dropdown-menu {:on-close (fn [event]
(dom/stop-propagation event)
(reset! show false))
:show @show}
[:ul.dropdown
[:li {:tab-index (if show
"0"
"-1")
:on-click (partial on-click :settings-profile)
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-click :settings-profile event)))
:data-test "profile-profile-opt"}
[:span.text (tr "labels.your-account")]]
[:li.separator {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://help.penpot.app")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://help.penpot.app")))
:data-test "help-center-profile-opt"}
[:span.text (tr "labels.help-center")]]
[:li {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://community.penpot.app")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://community.penpot.app")))}
[:span.text (tr "labels.community")]]
[:li {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://www.youtube.com/c/Penpot")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://www.youtube.com/c/Penpot")))}
[:span.text (tr "labels.tutorials")]]
[:li {:tab-index (if show
"0"
"-1")
:on-click show-release-notes
:on-key-down (fn [event]
(when (kbd/enter? event)
(show-release-notes)))}
[:span (tr "labels.release-notes")]]
[:li.separator {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://penpot.app/libraries-templates")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://penpot.app/libraries-templates")))
:data-test "libraries-templates-profile-opt"}
[:span.text (tr "labels.libraries-and-templates")]]
[:li {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://github.com/penpot/penpot")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://github.com/penpot/penpot")))}
[:span (tr "labels.github-repo")]]
[:li {:tab-index (if show
"0"
"-1")
:on-click #(dom/open-new-window "https://penpot.app/terms")
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/open-new-window "https://penpot.app/terms")))}
[:span (tr "auth.terms-of-service")]]
(when (contains? cf/flags :user-feedback)
[:li.separator {:tab-index (if show
"0"
"-1")
:on-click (partial on-click :settings-feedback)
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-click :settings-feedback event)))
:data-test "feedback-profile-opt"}
[:span.text (tr "labels.give-feedback")]])
[:li.separator {:tab-index (if show
"0"
"-1")
:on-click #(on-click (du/logout) %)
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-click (du/logout) event)))
:data-test "logout-profile-opt"}
[:span.icon i/exit]
[:span.text (tr "labels.logout")]]]]
(when (and team profile)
[:& comments-section
{:profile profile
:team team
:show? show-comments?
:on-show-comments handle-show-comments
:on-hide-comments handle-hide-comments}])])))
(mf/defc sidebar (mf/defc sidebar
{::mf/wrap-props false {::mf/wrap-props false
::mf/wrap [mf/memo]} ::mf/wrap [mf/memo]}
[props] [props]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [team (obj/get props "team")
team (obj/get props "team")
profile (obj/get props "profile")] profile (obj/get props "profile")]
(if new-css-system [:nav {:class (stl/css :dashboard-sidebar)}
[:nav {:class (stl/css :dashboard-sidebar)} [:> sidebar-content props]
[:> sidebar-content props] [:& profile-section
[:& profile-section {:profile profile
{:profile profile :team team}]]))
:team team}]]
[:nav.dashboard-sidebar
[:> sidebar-content props]
[:& profile-section
{:profile profile
:team team}]])))

File diff suppressed because it is too large Load Diff

View File

@ -102,7 +102,7 @@
} }
} }
.btn-primary { .btn-primary {
@extends .button-primary; @extend .button-primary;
height: $s-32; height: $s-32;
} }
} }
@ -650,6 +650,7 @@
color: var(--modal-title-foreground-color); color: var(--modal-title-foreground-color);
} }
} }
.invitation-row { .invitation-row {
margin-top: $s-8; margin-top: $s-8;
margin-bottom: $s-24; margin-bottom: $s-24;
@ -671,48 +672,56 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-container {
@include flexColumn; @extend .modal-container-base;
gap: $s-24; border: $s-1 solid var(--modal-border-color);
@include titleTipography; }
margin-bottom: $s-24;
.fields-row { .modal-header {
@include flexColumn; margin-bottom: $s-24;
.select-title { }
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.custom-input-checkbox {
align-items: flex-start;
}
}
}
.modal-footer { .modal-title {
.action-buttons { @include tabTitleTipography;
@extend .modal-action-btns; color: var(--modal-title-foreground-color);
button { }
@extend .modal-accept-btn;
} .modal-close-btn {
.cancel-button { @extend .modal-close-btn-base;
@extend .modal-cancel-btn; }
}
} .modal-content {
} @include flexColumn;
gap: $s-24;
@include titleTipography;
margin-bottom: $s-24;
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.custom-input-checkbox {
align-items: flex-start;
}
.hint {
color: var(--modal-text-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
}
.cancel-button {
@extend .modal-cancel-btn;
} }
} }

View File

@ -13,7 +13,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
@ -70,73 +69,42 @@
(mf/defc team-form-modal {::mf/register modal/components (mf/defc team-form-modal {::mf/register modal/components
::mf/register-as :team-form} ::mf/register-as :team-form}
[{:keys [team] :as props}] [{:keys [team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [initial (mf/use-memo (fn [] (or team {})))
initial (mf/use-memo (fn [] (or team {})))
form (fm/use-form :spec ::team-form form (fm/use-form :spec ::team-form
:validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space")) :validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space"))
(fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))] (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))]
:initial initial) :initial initial)
on-close #(st/emit! (modal/hide))] on-close #(st/emit! (modal/hide))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:& fm/form {:form form :on-submit on-submit}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-header)} [:div {:class (stl/css :modal-header)}
(if team (if team
[:h2 {:class (stl/css :modal-title)} [:h2 {:class (stl/css :modal-title)}
(tr "labels.rename-team")] (tr "labels.rename-team")]
[:h2 {:class (stl/css :modal-title)} [:h2 {:class (stl/css :modal-title)}
(tr "labels.create-team")]) (tr "labels.create-team")])
[:button {:class (stl/css :modal-close-btn) [:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]] :on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:& fm/input {:type "text" [:& fm/input {:type "text"
:auto-focus? true :auto-focus? true
:class (stl/css :group-name-input) :class (stl/css :group-name-input)
:form form :form form
:name :name :name :name
:placeholder "E.g. Design" :placeholder "E.g. Design"
:label (tr "labels.create-team.placeholder")}]] :label (tr "labels.create-team.placeholder")}]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:> fm/submit-button* [:> fm/submit-button*
{:label (if team {:label (if team
(tr "labels.update-team") (tr "labels.update-team")
(tr "labels.create-team")) (tr "labels.create-team"))
:className (stl/css :accept-btn)}]]]]]] :className (stl/css :accept-btn)}]]]]]]))
[:div.modal-overlay
[:div.modal-container.team-form-modal
[:& fm/form {:form form :on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
(if team
[:h2 (tr "labels.rename-team")]
[:h2 (tr "labels.create-team")])]
[:div.modal-close-button
{:on-click #(st/emit! (modal/hide))} i/close]]
[:div.modal-content.generic-form
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:label (tr "labels.create-team.placeholder")}]]
[:div.modal-footer
[:div.action-buttons
[:> fm/submit-button*
{:label (if team
(tr "labels.update-team")
(tr "labels.create-team"))}]]]]]])))

View File

@ -16,7 +16,6 @@
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
@ -59,8 +58,7 @@
(mf/defc title (mf/defc title
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [collapsed]}] [{:keys [collapsed]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-click
on-click
(mf/use-fn (mf/use-fn
(mf/deps collapsed) (mf/deps collapsed)
(fn [_event] (fn [_event]
@ -76,27 +74,17 @@
(dom/prevent-default event) (dom/prevent-default event)
(on-click event))))] (on-click event))))]
(if new-css-system [:div {:class (stl/css :title)}
[:div {:class (stl/css :title)} [:button {:tab-index "0"
[:button {:tab-index "0" :on-click on-click
:on-click on-click :on-key-down on-key-down}
:on-key-down on-key-down} [:span (tr "dashboard.libraries-and-templates")]
[:span (tr "dashboard.libraries-and-templates")] [:span {:class (stl/css :icon)} (if ^boolean collapsed i/arrow-up i/arrow-down)]]]))
[:span {:class (stl/css :icon)} (if ^boolean collapsed i/arrow-up i/arrow-down)]]]
;; OLD
[:div.title
[:button {:tab-index "0"
:on-click on-click
:on-key-down on-key-down}
[:span (tr "dashboard.libraries-and-templates")]
[:span.icon (if ^boolean collapsed i/arrow-up i/arrow-down)]]])))
(mf/defc card-item (mf/defc card-item
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [item index is-visible collapsed on-import]}] [{:keys [item index is-visible collapsed on-import]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [id (dm/str "card-container-" index)
id (dm/str "card-container-" index)
thb (assoc cf/public-uri :path (dm/str "/images/thumbnails/template-" (:id item) ".jpg")) thb (assoc cf/public-uri :path (dm/str "/images/thumbnails/template-" (:id item) ".jpg"))
on-click on-click
@ -113,41 +101,24 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(on-import item event))))] (on-import item event))))]
(if new-css-system [:a {:class (stl/css :card-container)
[:a :tab-index (if (or (not is-visible) collapsed) "-1" "0")
{:class (stl/css :card-container) :id id
:tab-index (if (or (not is-visible) collapsed) "-1" "0") :data-index index
:id id :on-click on-click
:data-index index :on-key-down on-key-down}
:on-click on-click [:div {:class (stl/css :template-card)}
:on-key-down on-key-down} [:div {:class (stl/css :img-container)}
[:div {:class (stl/css :template-card)} [:img {:src (dm/str thb)
[:div {:class (stl/css :img-container)} :alt (:name item)}]]
[:img {:src (dm/str thb) [:div {:class (stl/css :card-name)}
:alt (:name item)}]] [:span (:name item)]
[:div {:class (stl/css :card-name)} [:span {:class (stl/css :icon)} i/download]]]]))
[:span (:name item)]
[:span {:class (stl/css :icon)} i/download]]]]
;; OLD
[:a.card-container
{:tab-index (if (or (not is-visible) collapsed) "-1" "0")
:id id
:data-index index
:on-click on-click
:on-key-down on-key-down}
[:div.template-card
[:div.img-container
[:img {:src (dm/str thb)
:alt (:name item)}]]
[:div.card-name [:span (:name item)]
[:span.icon i/download]]]])))
(mf/defc card-item-link (mf/defc card-item-link
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [total is-visible collapsed section]}] [{:keys [total is-visible collapsed section]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [id (dm/str "card-container-" total)
id (dm/str "card-container-" total)
on-click on-click
(mf/use-fn (mf/use-fn
@ -165,39 +136,23 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(on-click event))))] (on-click event))))]
(if new-css-system [:div {:class (stl/css :card-container)}
[:div {:class (stl/css :card-container)} [:div {:class (stl/css :template-card)}
[:div {:class (stl/css :template-card)} [:div {:class (stl/css :img-container)}
[:div {:class (stl/css :img-container)} [:a {:id id
[:a {:id id :tab-index (if (or (not is-visible) collapsed) "-1" "0")
:tab-index (if (or (not is-visible) collapsed) "-1" "0") :href "https://penpot.app/libraries-templates.html"
:href "https://penpot.app/libraries-templates.html" :target "_blank"
:target "_blank" :on-click on-click
:on-click on-click :on-key-down on-key-down}
:on-key-down on-key-down} [:div {:class (stl/css :template-link)}
[:div {:class (stl/css :template-link)} [:div {:class (stl/css :template-link-title)} (tr "dashboard.libraries-and-templates")]
[:div {:class (stl/css :template-link-title)} (tr "dashboard.libraries-and-templates")] [:div {:class (stl/css :template-link-text)} (tr "dashboard.libraries-and-templates.explore")]]]]]]))
[:div {:class (stl/css :template-link-text)} (tr "dashboard.libraries-and-templates.explore")]]]]]]
;; OLD
[:div.card-container
[:div.template-card
[:div.img-container
[:a {:id id
:tab-index (if (or (not is-visible) collapsed) "-1" "0")
:href "https://penpot.app/libraries-templates.html"
:target "_blank"
:on-click on-click
:on-key-down on-key-down}
[:div.template-link
[:div.template-link-title (tr "dashboard.libraries-and-templates")]
[:div.template-link-text (tr "dashboard.libraries-and-templates.explore")]]]]]])))
(mf/defc templates-section (mf/defc templates-section
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [default-project-id profile project-id team-id content-width]}] [{:keys [default-project-id profile project-id team-id content-width]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [templates (mf/deref builtin-templates)
templates (mf/deref builtin-templates)
templates (mf/with-memo [templates] templates (mf/with-memo [templates]
(filterv #(not= (:id %) "tutorial-for-beginners") templates)) (filterv #(not= (:id %) "tutorial-for-beginners") templates))
@ -273,94 +228,50 @@
(mf/use-fn (mf/use-fn
(mf/deps default-project-id project-id section templates team-id) (mf/deps default-project-id project-id section templates team-id)
(fn [template _event] (fn [template _event]
(import-template! template team-id project-id default-project-id section))) (import-template! template team-id project-id default-project-id section)))]
]
(mf/with-effect [profile collapsed] (mf/with-effect [profile collapsed]
(when (and profile (not collapsed)) (when (and profile (not collapsed))
(st/emit! (dd/fetch-builtin-templates)))) (st/emit! (dd/fetch-builtin-templates))))
(if new-css-system [:div {:class (stl/css-case :dashboard-templates-section true
[:div :collapsed collapsed)}
{:class (stl/css-case :dashboard-templates-section true [:& title {:collapsed collapsed}]
:collapsed collapsed)}
[:& title {:collapsed collapsed}]
[:div {:class (stl/css :content) [:div {:class (stl/css :content)
:ref content-ref :ref content-ref
:style {:left card-offset :style {:left card-offset
:width (dm/str container-size "px")}} :width (dm/str container-size "px")}}
(for [index (range (count templates))] (for [index (range (count templates))]
[:& card-item [:& card-item
{:on-import on-import-template {:on-import on-import-template
:item (nth templates index) :item (nth templates index)
:index index :index index
:key index :key index
:is-visible (and (>= index first-card) :is-visible (and (>= index first-card)
(<= index last-card)) (<= index last-card))
:collapsed collapsed}]) :collapsed collapsed}])
[:& card-item-link [:& card-item-link
{:is-visible (and (>= total first-card) (<= total last-card)) {:is-visible (and (>= total first-card) (<= total last-card))
:collapsed collapsed :collapsed collapsed
:section section :section section
:total total}]] :total total}]]
(when (< card-offset 0) (when (< card-offset 0)
[:button [:button
{:class (stl/css :button :left) {:class (stl/css :button :left)
:tab-index (if ^boolean collapsed "-1" "0") :tab-index (if ^boolean collapsed "-1" "0")
:on-click on-move-left :on-click on-move-left
:on-key-down on-move-left-key-down} :on-key-down on-move-left-key-down}
i/go-prev]) i/go-prev])
(when more-cards (when more-cards
[:button [:button
{:class (stl/css :button :right) {:class (stl/css :button :right)
:tab-index (if collapsed "-1" "0") :tab-index (if collapsed "-1" "0")
:on-click on-move-right :on-click on-move-right
:aria-label (tr "labels.next") :aria-label (tr "labels.next")
:on-key-down on-move-right-key-down} :on-key-down on-move-right-key-down}
i/go-next])] i/go-next])]))
;; OLD
[:div.dashboard-templates-section
{:class (when ^boolean collapsed "collapsed")}
[:& title {:collapsed collapsed}]
[:div.content {:ref content-ref
:style {:left card-offset
:width (dm/str container-size "px")}}
(for [index (range (count templates))]
[:& card-item
{:on-import on-import-template
:item (nth templates index)
:index index
:key index
:is-visible (and (>= index first-card)
(<= index last-card))
:collapsed collapsed}])
[:& card-item-link
{:is-visible (and (>= total first-card) (<= total last-card))
:collapsed collapsed
:section section
:total total}]]
(when (< card-offset 0)
[:button.button.left
{:tab-index (if ^boolean collapsed "-1" "0")
:on-click on-move-left
:on-key-down on-move-left-key-down}
i/go-prev])
(when more-cards
[:button.button.right
{:tab-index (if collapsed "-1" "0")
:on-click on-move-right
:aria-label (tr "labels.next")
:on-key-down on-move-right-key-down}
i/go-next])])))

View File

@ -11,7 +11,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,7 @@
::mf/register-as :delete-shared-libraries ::mf/register-as :delete-shared-libraries
::mf/wrap-props false} ::mf/wrap-props false}
[{:keys [ids on-accept on-cancel accept-style origin count-libraries]}] [{:keys [ids on-accept on-cancel accept-style origin count-libraries]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [references* (mf/use-state {})
references* (mf/use-state {})
references (deref references*) references (deref references*)
on-accept (or on-accept noop) on-accept (or on-accept noop)
@ -96,91 +94,43 @@
(let [key (events/listen js/document "keydown" on-keydown)] (let [key (events/listen js/document "keydown" on-keydown)]
(partial events/unlistenByKey key)))) (partial events/unlistenByKey key))))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} title]
[:h2 {:class (stl/css :modal-title)} title] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click cancel-fn} i/close-refactor]]
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(when (and (string? subtitle) (not= subtitle "")) (when (and (string? subtitle) (not= subtitle ""))
[:h3 {:class (stl/css :modal-subtitle)} subtitle]) [:h3 {:class (stl/css :modal-subtitle)} subtitle])
(when (not= 0 count-libraries) (when (not= 0 count-libraries)
(if (pos? (count references)) (if (pos? (count references))
[:* [:*
[:div [:div
(when (and (string? scd-msg) (not= scd-msg "")) (when (and (string? scd-msg) (not= scd-msg ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-msg]) [:h3 {:class (stl/css :modal-scd-msg)} scd-msg])
[:ul {:class (stl/css :element-list)} [:ul {:class (stl/css :element-list)}
(for [[file-id file-name] references] (for [[file-id file-name] references]
[:li {:class (stl/css :list-item) [:li {:class (stl/css :list-item)
:key (dm/str file-id)} :key (dm/str file-id)}
[:span "- " file-name]])]] [:span "- " file-name]])]]
(when (and (string? hint) (not= hint "")) (when (and (string? hint) (not= hint ""))
[:h3 {:class (stl/css :modal-hint)}hint])] [:h3 {:class (stl/css :modal-hint)} hint])]
[:* [:*
[:h3 {:class (stl/css :modal-msg)} no-files-msg]]))] [:h3 {:class (stl/css :modal-msg)} no-files-msg]]))]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit) (when-not (= cancel-label :omit)
[:input {:class (stl/css :cancel-button) [:input {:class (stl/css :cancel-button)
:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button" :type "button"
:value accept-label :value cancel-label
:on-click accept-fn}]]]]] :on-click cancel-fn}])
[:input {:class (stl/css-case :accept-btn true
[:div.modal-overlay :danger (= accept-style :danger)
[:div.modal-container.confirm-dialog :primary (= accept-style :primary))
[:div.modal-header :type "button"
[:div.modal-header-title :value accept-label
[:h2 title]] :on-click accept-fn}]]]]]))
[:div.modal-close-button
{:on-click cancel-fn} i/close]]
[:div.modal-content.delete-shared
(when (and (string? subtitle) (not= subtitle ""))
[:h3 subtitle])
(when (not= 0 count-libraries)
(if (pos? (count references))
[:*
[:div
(when (and (string? scd-msg) (not= scd-msg ""))
[:h3 scd-msg])
[:ul.file-list
(for [[file-id file-name] references]
[:li.modal-item-element
{:key (dm/str file-id)}
[:span "- " file-name]])]]
(when (and (string? hint) (not= hint ""))
[:h3 hint])]
[:*
[:h3 no-files-msg]]))]
[:div.modal-footer
[:div.action-buttons
(when-not (= cancel-label :omit)
[:input.cancel-button
{:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]
)
))

View File

@ -11,45 +11,53 @@
&.transparent { &.transparent {
background-color: transparent; background-color: transparent;
} }
.modal-container { }
@extend .modal-container-base;
.modal-header { .modal-container {
margin-bottom: $s-24; @extend .modal-container-base;
.modal-title { }
@include tabTitleTipography;
color: var(--modal-title-foreground-color); .modal-header {
} margin-bottom: $s-24;
.modal-close-btn { }
@extend .modal-close-btn-base;
} .modal-title {
} @include tabTitleTipography;
.modal-content { color: var(--modal-title-foreground-color);
@include titleTipography; }
margin-bottom: $s-24;
.modal-hint { .modal-close-btn {
@extend .modal-hint-base; @extend .modal-close-btn-base;
} }
.element-list {
@include titleTipography; .modal-content {
.list-item { @include titleTipography;
@include titleTipography; margin-bottom: $s-24;
} }
}
} .modal-hint {
.modal-footer { @extend .modal-hint-base;
.action-buttons { }
@extend .modal-action-btns;
.cancel-button { .element-list {
@extend .modal-cancel-btn; @include titleTipography;
} .list-item {
.accept-btn { @include titleTipography;
@extend .modal-accept-btn; }
&.danger { }
@extend .modal-danger-btn;
} .action-buttons {
} @extend .modal-action-btns;
} }
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
} }
} }

View File

@ -14,96 +14,52 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.link-button :as lb] [app.main.ui.components.link-button :as lb]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc banner (mf/defc banner
[{:keys [type position status controls content links actions on-close data-test role] :as props}] [{:keys [type position status controls content links actions on-close data-test role] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css-case :banner true
(if new-css-system :warning (= type :warning)
[:div {:class (stl/css-case :banner true :error (= type :error)
:warning (= type :warning) :success (= type :success)
:error (= type :error) :info (= type :info)
:success (= type :success) :fixed (= position :fixed)
:info (= type :info) :floating (= position :floating)
:fixed (= position :fixed) :inline (= position :inline)
:floating (= position :floating) :hide (= status :hide))}
:inline (= position :inline) [:div {:class (stl/css :wrapper)}
:hide (= status :hide))} [:div {:class (stl/css :icon)}
[:div {:class (stl/css :wrapper)} (case type
[:div {:class (stl/css :icon)} :warning i/msg-warning-refactor
(case type :error i/msg-error-refactor
:warning i/msg-warning-refactor :success i/msg-success-refactor
:error i/msg-error-refactor :info i/msg-neutral-refactor
:success i/msg-success-refactor i/msg-error-refactor)]
:info i/msg-neutral-refactor
i/msg-error-refactor)]
[:div {:class (stl/css-case :content true [:div {:class (stl/css-case :content true
:inline-actions (= controls :inline-actions) :inline-actions (= controls :inline-actions)
:bottom-actions (= controls :bottom-actions)) :bottom-actions (= controls :bottom-actions))
:data-test data-test :data-test data-test
:role role} :role role}
[:span {:class (stl/css :text)} [:span {:class (stl/css :text)}
content content
(for [[index link] (d/enumerate links)] (for [[index link] (d/enumerate links)]
[:* {:key (dm/str "link-" index)} [:* {:key (dm/str "link-" index)}
" " [:& lb/link-button {:class "link" " " [:& lb/link-button {:class "link"
:on-click (:callback link) :on-click (:callback link)
:value (:label link)}]])] :value (:label link)}]])]
(when (or (= controls :bottom-actions) (= controls :inline-actions)) (when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div {:class (stl/css :actions)} [:div {:class (stl/css :actions)}
(for [action actions] (for [action actions]
[:button {:key (uuid/next) [:button {:key (uuid/next)
:class (stl/css :action-bnt) :class (stl/css :action-bnt)
:on-click (:callback action)} :on-click (:callback action)}
(:label action)])])] (:label action)])])]
(when (= controls :close) (when (= controls :close)
[:button {:class (stl/css :btn-close) [:button {:class (stl/css :btn-close)
:on-click on-close} i/close-refactor])]] :on-click on-close} i/close-refactor])]])
[:div.banner {:class (dom/classnames
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
:info (= type :info)
:fixed (= position :fixed)
:floating (= position :floating)
:inline (= position :inline)
:hide (= status :hide))}
[:div.wrapper
[:div.icon (case type
:warning i/msg-warning
:error i/msg-error
:success i/msg-success
:info i/msg-info
i/msg-error)]
[:div.content {:class (dom/classnames
:inline-actions (= controls :inline-actions)
:bottom-actions (= controls :bottom-actions))
:data-test data-test
:role role}
[:span
content
(for [[index link] (d/enumerate links)]
[:* {:key (dm/str "link-" index)}
" " [:& lb/link-button {:class "link"
:on-click (:callback link)
:value (:label link)}]])]
(when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div.actions
(for [action actions]
[:div.btn-secondary.btn-small {:key (uuid/next)
:on-click (:callback action)}
(:label action)])])]
(when (= controls :close)
[:div.btn-close {:on-click on-close} i/close])]])))
(mf/defc notifications (mf/defc notifications
[] []

View File

@ -100,15 +100,6 @@
@include titleTipography; @include titleTipography;
} }
.inline-actions {
}
.bottom-actions {
}
.actions {
}
.action-btn { .action-btn {
@extend .button-tertiary; @extend .button-tertiary;
height: $s-32; height: $s-32;

View File

@ -51,7 +51,6 @@
(let [data (unchecked-get props "data") (let [data (unchecked-get props "data")
wrapper-ref (mf/use-ref nil) wrapper-ref (mf/use-ref nil)
components (mf/deref dm/components) components (mf/deref dm/components)
new-css-system (mf/use-ctx ctx/new-css-system)
allow-click-outside (:allow-click-outside data) allow-click-outside (:allow-click-outside data)
@ -78,9 +77,7 @@
(when-let [component (get components (:type data))] (when-let [component (get components (:type data))]
[:div {:ref wrapper-ref [:div {:ref wrapper-ref
:class (stl/css-case :class (stl/css :modal-wrapper)}
:modal-wrapper new-css-system
:global/modal-wrapper (not new-css-system))}
(mf/element component (:props data))]))) (mf/element component (:props data))])))
(def modal-ref (def modal-ref

View File

@ -13,7 +13,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.onboarding.newsletter] [app.main.ui.onboarding.newsletter]
[app.main.ui.onboarding.questions] [app.main.ui.onboarding.questions]
[app.main.ui.onboarding.team-choice] [app.main.ui.onboarding.team-choice]
@ -33,178 +32,113 @@
(mf/defc onboarding-welcome (mf/defc onboarding-welcome
[{:keys [next] :as props}] [{:keys [next] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [go-next
go-next
(fn [] (fn []
(send-event "onboarding-step1-continue") (send-event "onboarding-step1-continue")
(next))] (next))]
(if new-css-system [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :modal-left)} [:img {:src "images/onboarding-welcome.png"
[:img {:src "images/onboarding-welcome.png" :border "0"
:border "0" :alt (tr "onboarding.welcome.alt")}]]
:alt (tr "onboarding.welcome.alt")}]] [:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :modal-right)} [:div {:class (stl/css :release)}
[:div {:class (stl/css :release)} "Version " (:main cf/version)]
"Version " (:main cf/version)] [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)
[:h2 {:class (stl/css :modal-title) :data-test "onboarding-welcome"}
:data-test "onboarding-welcome"} (tr "onboarding-v2.welcome.title")]]
(tr "onboarding-v2.welcome.title")]]
[:div {:class (stl/css :modal-info)} [:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.welcome.desc1")] (tr "onboarding-v2.welcome.desc1")]
[:div {:class (stl/css :property-block)} [:div {:class (stl/css :property-block)}
[:img {:src "images/community.svg" [:img {:src "images/community.svg"
:border "0"}] :border "0"}]
[:div {:class (stl/css :text-wrapper)} [:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)} [:div {:class (stl/css :property-title)}
[:a {:href "https://community.penpot.app/" [:a {:href "https://community.penpot.app/"
:target "_blank" :target "_blank"
:on-click #(send-event "onboarding-community-link")} :on-click #(send-event "onboarding-community-link")}
(tr "onboarding-v2.welcome.desc2.title")]] (tr "onboarding-v2.welcome.desc2.title")]]
[:div {:class (stl/css :property-description)} [:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc2")]]] (tr "onboarding-v2.welcome.desc2")]]]
[:div {:class (stl/css :property-block)} [:div {:class (stl/css :property-block)}
[:img {:src "images/contributing.svg" [:img {:src "images/contributing.svg"
:border "0"}] :border "0"}]
[:div {:class (stl/css :text-wrapper)} [:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)} [:div {:class (stl/css :property-title)}
[:a {:href "https://help.penpot.app/contributing-guide/" [:a {:href "https://help.penpot.app/contributing-guide/"
:target "_blank" :on-click #(send-event "onboarding-contributing-link")} :target "_blank" :on-click #(send-event "onboarding-contributing-link")}
(tr "onboarding-v2.welcome.desc3.title")]] (tr "onboarding-v2.welcome.desc3.title")]]
[:div {:class (stl/css :property-description)} [:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc3")]]]]] (tr "onboarding-v2.welcome.desc3")]]]]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next [:button {:on-click go-next
:data-test "onboarding-next-btn"} :data-test "onboarding-next-btn"}
(tr "labels.continue")]]]] (tr "labels.continue")]]]]))
[:div.modal-container.onboarding.onboarding-v2
[:div.modal-left.welcome
[:img {:src "images/onboarding-welcome.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
[:div.modal-right
[:div.release-container [:span.release "Version " (:main cf/version)]]
[:div.right-content
[:div.modal-title
[:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.welcome.title")]]
[:div.modal-content
[:p (tr "onboarding-v2.welcome.desc1")]
[:div.welcome-card
[:img {:src "images/community.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://community.penpot.app/" :target "_blank" :on-click #(send-event "onboarding-community-link")} (tr "onboarding-v2.welcome.desc2.title")]]
[:div.description (tr "onboarding-v2.welcome.desc2")]]]
[:div.welcome-card
[:img {:src "images/contributing.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://help.penpot.app/contributing-guide/" :target "_blank" :on-click #(send-event "onboarding-contributing-link")} (tr "onboarding-v2.welcome.desc3.title")]]
[:div.description (tr "onboarding-v2.welcome.desc3")]]]]]
[:div.modal-navigation
[:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
(mf/defc onboarding-before-start (mf/defc onboarding-before-start
[{:keys [next] :as props}] [{:keys [next] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [go-next
go-next
(fn [] (fn []
(send-event "onboarding-step2-continue") (send-event "onboarding-step2-continue")
(next))] (next))]
(if new-css-system [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :modal-left)} [:img {:src "images/onboarding-people.png"
[:img {:src "images/onboarding-people.png" :border "0"
:border "0" :alt (tr "onboarding.welcome.alt")}]]
:alt (tr "onboarding.welcome.alt")}]] [:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :modal-right)} [:div {:class (stl/css :release)}
[:div {:class (stl/css :release)} "Version " (:main cf/version)]
"Version " (:main cf/version)] [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)
[:h2 {:class (stl/css :modal-title) :data-test "onboarding-welcome"}
:data-test "onboarding-welcome"} (tr "onboarding-v2.before-start.title")]]
(tr "onboarding-v2.before-start.title")]]
[:div {:class (stl/css :modal-info)} [:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.before-start.desc1")] (tr "onboarding-v2.before-start.desc1")]
[:div {:class (stl/css :property-block)} [:div {:class (stl/css :property-block)}
[:img {:src "images/user-guide.svg" :border "0"}] [:img {:src "images/user-guide.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)} [:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)} [:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link) [:a {:class (stl/css :modal-link)
:href "https://help.penpot.app/user-guide/" :href "https://help.penpot.app/user-guide/"
:target "_blank" :target "_blank"
:on-click #(send-event "onboarding-user-guide-link")} :on-click #(send-event "onboarding-user-guide-link")}
(tr "onboarding-v2.before-start.desc2.title")]] (tr "onboarding-v2.before-start.desc2.title")]]
[:div {:class (stl/css :property-description)} [:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc2")]]] (tr "onboarding-v2.before-start.desc2")]]]
[:div {:class (stl/css :property-block)} [:div {:class (stl/css :property-block)}
[:img {:src "images/video-tutorials.svg" :border "0"}] [:img {:src "images/video-tutorials.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)} [:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)} [:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link) [:a {:class (stl/css :modal-link)
:href "https://www.youtube.com/c/Penpot" :href "https://www.youtube.com/c/Penpot"
:target "_blank" :target "_blank"
:on-click #(send-event "onboarding-video-tutorials-link")} :on-click #(send-event "onboarding-video-tutorials-link")}
(tr "onboarding-v2.before-start.desc3.title")]] (tr "onboarding-v2.before-start.desc3.title")]]
[:div {:class (stl/css :property-description)} [:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc3")]]]]] (tr "onboarding-v2.before-start.desc3")]]]]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next [:button {:on-click go-next
:data-test "onboarding-next-btn"} :data-test "onboarding-next-btn"}
(tr "labels.continue")]]]] (tr "labels.continue")]]]]))
[:div.modal-container.onboarding.onboarding-v2
[:div.modal-left.welcome
[:img {:src "images/onboarding-people.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
[:div.modal-right
[:div.release-container [:span.release "Version " (:main cf/version)]]
[:div.right-content
[:div.modal-title
[:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.before-start.title")]]
[:div.modal-content
[:p (tr "onboarding-v2.before-start.desc1")]
[:div.welcome-card
[:img {:src "images/user-guide.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://help.penpot.app/user-guide/" :target "_blank" :on-click #(send-event "onboarding-user-guide-link")} (tr "onboarding-v2.before-start.desc2.title")]]
[:div.description (tr "onboarding-v2.before-start.desc2")]]]
[:div.welcome-card
[:img {:src "images/video-tutorials.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://www.youtube.com/c/Penpot" :target "_blank" :on-click #(send-event "onboarding-video-tutorials-link")} (tr "onboarding-v2.before-start.desc3.title")]]
[:div.description (tr "onboarding-v2.before-start.desc3")]]]]]
[:div.modal-navigation
[:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
(mf/defc onboarding-modal (mf/defc onboarding-modal
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :onboarding} ::mf/register-as :onboarding}
[_] [_]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [slide (mf/use-state :start)
slide (mf/use-state :start)
klass (mf/use-state "fadeInDown") klass (mf/use-state "fadeInDown")
navigate navigate
@ -230,15 +164,8 @@
(reset! klass nil) (reset! klass nil)
(tm/dispose! sem)))) (tm/dispose! sem))))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div.animated {:class (dm/str @klass " " (stl/css :animated))}
[:div.animated {:class(dm/str @klass " " (stl/css :animated))} (case @slide
(case @slide :start [:& onboarding-welcome {:next #(navigate :opensource)}]
:start [:& onboarding-welcome {:next #(navigate :opensource)}] :opensource [:& onboarding-before-start {:next skip}])]]))
:opensource [:& onboarding-before-start {:next skip}])]]
[:div.modal-overlay
[:div.animated {:class @klass}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]])))

View File

@ -11,7 +11,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -20,8 +19,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :onboarding-newsletter-modal} ::mf/register-as :onboarding-newsletter-modal}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [message (tr "onboarding.newsletter.acceptance-message")
message (tr "onboarding.newsletter.acceptance-message")
newsletter-updates (mf/use-state false) newsletter-updates (mf/use-state false)
newsletter-news (mf/use-state false) newsletter-news (mf/use-state false)
toggle toggle
@ -39,78 +37,49 @@
(modal/show {:type :onboarding-team}) (modal/show {:type :onboarding-team})
(du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))] (du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div.animated.fadeInDown {:class (stl/css :modal-container)}
[:div.animated.fadeInDown {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)
[:h2 {:class (stl/css :modal-title) :data-test "onboarding-newsletter-title"}
:data-test "onboarding-newsletter-title"} (tr "onboarding.newsletter.title")]
(tr "onboarding.newsletter.title")] [:p {:class (stl/css :modal-text)}
[:p {:class (stl/css :modal-text)} (tr "onboarding-v2.newsletter.desc")]]
(tr "onboarding-v2.newsletter.desc")]] [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :newsletter-options)}
[:div {:class (stl/css :newsletter-options)} [:div {:class (stl/css :input-wrapper)}
[:div {:class (stl/css :input-wrapper)} [:label {:for "newsletter-updates"}
[:label {:for "newsletter-updates"} [:span {:class (stl/css-case :global/checked @newsletter-updates)}
[:span {:class (stl/css-case :global/checked @newsletter-updates)} (when @newsletter-updates
(when @newsletter-updates i/status-tick-refactor)]
i/status-tick-refactor)] (tr "onboarding-v2.newsletter.updates")
(tr "onboarding-v2.newsletter.updates") [:input {:type "checkbox"
[:input {:type "checkbox" :id "newsletter-updates"
:id "newsletter-updates" :on-change #(toggle newsletter-updates)}]]]
:on-change #(toggle newsletter-updates)}]]]
[:div {:class (stl/css :input-wrapper)} [:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-news"} [:label {:for "newsletter-news"}
[:span {:class (stl/css-case :global/checked @newsletter-news)} [:span {:class (stl/css-case :global/checked @newsletter-news)}
(when @newsletter-news (when @newsletter-news
i/status-tick-refactor)] i/status-tick-refactor)]
(tr "onboarding-v2.newsletter.news") (tr "onboarding-v2.newsletter.news")
[:input {:type "checkbox" [:input {:type "checkbox"
:id "newsletter-news" :id "newsletter-news"
:on-change #(toggle newsletter-news)}]]]] :on-change #(toggle newsletter-news)}]]]]
[:div {:class (stl/css :modal-info)} [:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy1") (tr "onboarding-v2.newsletter.privacy1")
[:a {:class (stl/css :modal-link) [:a {:class (stl/css :modal-link)
:target "_blank" :target "_blank"
:href "https://penpot.app/privacy"} :href "https://penpot.app/privacy"}
(tr "onboarding.newsletter.policy")]] (tr "onboarding.newsletter.policy")]]
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy2")]]] (tr "onboarding-v2.newsletter.privacy2")]]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:button {:on-click accept} (tr "labels.continue")]] [:button {:on-click accept} (tr "labels.continue")]]
[:img {:class (stl/css-case :deco true [:img {:class (stl/css-case :deco true
:top true) :top true)
:src "images/deco-newsletter.png" :border "0"}]]] :src "images/deco-newsletter.png" :border "0"}]]]))
[:div.modal-overlay
[:div.modal-container.onboarding.newsletter.animated.fadeInDown
[:div.modal-top
[:h1.newsletter-title {:data-test "onboarding-newsletter-title"} (tr "onboarding.newsletter.title")]
[:p (tr "onboarding-v2.newsletter.desc")]]
[:div.modal-bottom
[:div.newsletter-options
[:div.input-checkbox.check-primary
[:input {:type "checkbox"
:id "newsletter-updates"
:on-change #(toggle newsletter-updates)}]
[:label {:for "newsletter-updates"} (tr "onboarding-v2.newsletter.updates")]]
[:div.input-checkbox.check-primary
[:input {:type "checkbox"
:id "newsletter-news"
:on-change #(toggle newsletter-news)}]
[:label {:for "newsletter-news"} (tr "onboarding-v2.newsletter.news")]]]
[:p (tr "onboarding-v2.newsletter.privacy1") [:a {:target "_blank" :href "https://penpot.app/privacy"} (tr "onboarding.newsletter.policy")]]
[:p (tr "onboarding-v2.newsletter.privacy2")]]
[:div.modal-footer
[:button.btn-primary {:on-click accept} (tr "labels.continue")]]
[:img.deco.top {:src "images/deco-newsletter.png" :border "0"}]
[:img.deco.newsletter-left {:src "images/deco-news-left.png" :border "0"}]
[:img.deco.newsletter-right {:src "images/deco-news-right.png" :border "0"}]]])
))

View File

@ -13,7 +13,6 @@
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -22,139 +21,75 @@
(mf/defc step-container (mf/defc step-container
[{:keys [form step on-next on-prev children] :as props}] [{:keys [form step on-next on-prev children] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:& fm/form {:form form :on-submit on-next}
[:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)]
(if new-css-system children
[:& fm/form {:form form :on-submit on-next}
[:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)]
children [:div {:class (stl/css :action-buttons)}
[:div {:class (stl/css :action-buttons)} (when on-prev
[:button {:class (stl/css :prev-button)
:on-click on-prev} (tr "questions.previous")])
(when on-prev [:> fm/submit-button*
[:button {:class (stl/css :prev-button) {:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
:on-click on-prev} (tr "questions.previous")]) :class (stl/css :next-button)}]]])
[:> fm/submit-button*
{:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
:class (stl/css :next-button)}]]]
[:& fm/form {:form form :on-submit on-next}
[:div.step-header
[:div.step-number (str/ffmt "%/4" step)]]
children
[:div.buttons
[:div.step-next
[:> fm/submit-button*
{:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
:class "step-next"}]]
(when on-prev
[:div.step-prev
[:button {:on-click on-prev} (tr "questions.previous")]])]])))
(s/def ::questions-form-step-1 (s/def ::questions-form-step-1
(s/keys :req-un [::planning])) (s/keys :req-un [::planning]))
(mf/defc step-1 (mf/defc step-1
[{:keys [on-next form] :as props}] [{:keys [on-next form] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:& step-container {:form form :step 1 :on-next on-next}
(if new-css-system [:img {:class (stl/css :header-image)
[:& step-container {:form form :step 1 :on-next on-next} :src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
[:img {:class (stl/css :header-image) [:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")]
:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}] [:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")]
[:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")] [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.questions-how-are-you-planning-to-use-penpot")]
[:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")] [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.questions-how-are-you-planning-to-use-penpot")] {:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true} {:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"}
{:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"} {:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
{:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"} {:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"}
{:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"} {:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
{:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"} {:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
{:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"} {:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}]
{:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"} :default ""
{:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}] :name :planning}]])
:default ""
:name :planning}]]
[:& step-container {:form form :step 1 :on-next on-next}
[:img.header-image {:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
[:h1 (tr "questions.lets-get-started")]
[:p.intro (tr "questions.your-feedback-will-help-us")]
[:h3 (tr "questions.questions-how-are-you-planning-to-use-penpot")]
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "questions-how-are-you-planning-to-use-penpot" :disabled true}
{:label (tr "questions.discover-more-about-penpot") :value "discover-more-about-penpot" :key "discover-more-about-penpot"}
{:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team") :value "test-penpot-to-see-if-its-a-fit-for-team" :key "test-penpot-to-see-if-its-a-fit-for-team"}
{:label (tr "questions.start-to-work-on-my-project") :value "start-to-work-on-my-project" :key "start-to-work-on-my-project"}
{:label (tr "questions.get-the-code-from-my-team-project") :value "get-the-code-from-my-team-project" :key "get-the-code-from-my-team-project"}
{:label (tr "questions.leave-feedback-for-my-team-project") :value "leave-feedback-for-my-team-project" :key "leave-feedback-for-my-team-project"}
{:label (tr "questions.work-in-concept-ideas") :value "work-in-concept-ideas" :key "work-in-concept-ideas"}
{:label (tr "questions.try-out-before-using-penpot-on-premise") :value "try-out-before-using-penpot-on-premise" :key "try-out-before-using-penpot-on-premise"}]
:default ""
:name :planning}]])))
(s/def ::questions-form-step-2 (s/def ::questions-form-step-2
(s/keys :req-un [::experience-branding-illustrations-marketing-pieces ::experience-interface-design-visual-assets-design-systems ::experience-interface-wireframes-user-journeys-flows-navigation-trees])) (s/keys :req-un [::experience-branding-illustrations-marketing-pieces ::experience-interface-design-visual-assets-design-systems ::experience-interface-wireframes-user-journeys-flows-navigation-trees]))
(mf/defc step-2 (mf/defc step-2
[{:keys [on-next on-prev form] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
(if new-css-system [:h3 {:class (stl/css :modal-subtitle)}
[:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev} (tr "questions.describe-your-experience-working-on")]
[:h3 {:class (stl/css :modal-subtitle)}
(tr "questions.describe-your-experience-working-on")]
[:div {:class (stl/css :modal-question)} [:div {:class (stl/css :modal-question)}
[:div {:class (stl/css :modal-text)} [:div {:class (stl/css :modal-text)}
(tr "branding-illustrations-marketing-pieces")] (tr "branding-illustrations-marketing-pieces")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-branding-illustrations-marketing-pieces}]] :name :experience-branding-illustrations-marketing-pieces}]]
[:div {:class (stl/css :modal-question)} [:div {:class (stl/css :modal-question)}
[:div {:class (stl/css :modal-text)} [:div {:class (stl/css :modal-text)}
(tr "questions.interface-design-visual-assets-design-systems")] (tr "questions.interface-design-visual-assets-design-systems")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-design-visual-assets-design-systems}]] :name :experience-interface-design-visual-assets-design-systems}]]
[:div {:class (stl/css :modal-question)} [:div {:class (stl/css :modal-question)}
[:div {:class (stl/css :modal-text)} [:div {:class (stl/css :modal-text)}
(tr "questions.wireframes-user-journeys-flows-navigation-trees")] (tr "questions.wireframes-user-journeys-flows-navigation-trees")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"} [:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"} {:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}] {:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]]] :name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]]])
[:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev}
[:h3 (tr "questions.describe-your-experience-working-on")]
[:div.section (tr "branding-illustrations-marketing-pieces")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-branding-illustrations-marketing-pieces}]
[:div.section (tr "questions.interface-design-visual-assets-design-systems")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-design-visual-assets-design-systems}]
[:div.section (tr "questions.wireframes-user-journeys-flows-navigation-trees")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-wireframes-user-journeys-flows-navigation-trees}]])))
(s/def ::questions-form-step-3 (s/def ::questions-form-step-3
(s/keys :req-un [::experience-design-tool] (s/keys :req-un [::experience-design-tool]
@ -170,8 +105,7 @@
(mf/defc step-3 (mf/defc step-3
[{:keys [on-next on-prev form] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
on-design-tool-change on-design-tool-change
(fn [_ _] (fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])] (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
@ -180,40 +114,23 @@
(swap! form d/dissoc-in [:data :experience-design-tool-other]) (swap! form d/dissoc-in [:data :experience-design-tool-other])
(swap! form d/dissoc-in [:errors :experience-design-tool-other])))))] (swap! form d/dissoc-in [:errors :experience-design-tool-other])))))]
(if new-css-system [:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
[:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev} [:h3 {:class (stl/css :modal-subtitle)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "question.design-tool-more-experienced-with")]
(tr "question.design-tool-more-experienced-with")] [:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
[:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"} {:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"}
{:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"} {:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"}
{:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"} {:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"}
{:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"} {:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"}
{:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"} {:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
{:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"} {:label (tr "questions.other") :value "other"}]
{:label (tr "questions.other") :value "other"}] :name :experience-design-tool
:name :experience-design-tool :on-change on-design-tool-change}]
:on-change on-design-tool-change}]
[:& fm/input {:name :experience-design-tool-other [:& fm/input {:name :experience-design-tool-other
:placeholder (tr "questions.other") :placeholder (tr "questions.other")
:label "" :label ""
:disabled (not= experience-design-tool "other")}]] :disabled (not= experience-design-tool "other")}]]))
[:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev}
[:h3 (tr "question.design-tool-more-experienced-with")]
[:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png"}
{:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png"}
{:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png"}
{:label (tr "questions.canva") :value "canva" :image "images/form/canva.png"}
{:label (tr "questions.invision") :value "invision" :image "images/form/invision.png"}
{:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
{:label (tr "questions.other") :value "other"}]
:name :experience-design-tool
:on-change on-design-tool-change}]
[:div.other
[:label (tr "questions.other")]
[:& fm/input {:name :experience-design-tool-other :label (tr "questions.other") :disabled (not= experience-design-tool "other")}]]])))
(s/def ::questions-form-step-4 (s/def ::questions-form-step-4
(s/keys :req-un [::team-size ::role] (s/keys :req-un [::team-size ::role]
@ -229,8 +146,7 @@
(mf/defc step-4 (mf/defc step-4
[{:keys [on-next on-prev form] :as props}] [{:keys [on-next on-prev form] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [role (dm/get-in @form [:data :role])
role (dm/get-in @form [:data :role])
on-role-change on-role-change
(fn [_ _] (fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])] (let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
@ -239,63 +155,34 @@
(swap! form d/dissoc-in [:data :role-other]) (swap! form d/dissoc-in [:data :role-other])
(swap! form d/dissoc-in [:errors :role-other])))))] (swap! form d/dissoc-in [:errors :role-other])))))]
(if new-css-system [:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev} [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.role")]
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.role")] [:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
[:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"} {:label (tr "questions.developer") :value "developer"}
{:label (tr "questions.developer") :value "developer"} {:label (tr "questions.manager") :value "manager"}
{:label (tr "questions.manager") :value "manager"} {:label (tr "questions.founder") :value "founder"}
{:label (tr "questions.founder") :value "founder"} {:label (tr "questions.marketing") :value "marketing"}
{:label (tr "questions.marketing") :value "marketing"} {:label (tr "questions.student-teacher") :value "student-teacher"}
{:label (tr "questions.student-teacher") :value "student-teacher"} {:label (tr "questions.other") :value "other"}]
{:label (tr "questions.other") :value "other"}] :name :role
:name :role :on-change on-role-change}]
:on-change on-role-change}] [:& fm/input {:name :role-other :label "" :placeholder (tr "questions.other") :disabled (not= role "other")}]
[:& fm/input {:name :role-other :label "" :placeholder (tr "questions.other") :disabled (not= role "other")}]
[:div {:class (stl/css :modal-question)} [:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")] [:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")]
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true} [:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
{:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"} {:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
{:label (tr "questions.31-50") :value "31-50" :key "31-50"} {:label (tr "questions.31-50") :value "31-50" :key "31-50"}
{:label (tr "questions.11-30") :value "11-30" :key "11-30"} {:label (tr "questions.11-30") :value "11-30" :key "11-30"}
{:label (tr "questions.2-10") :value "2-10" :key "2-10"} {:label (tr "questions.2-10") :value "2-10" :key "2-10"}
{:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"} {:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
{:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}] {:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
:default "" :default ""
:name :team-size}]]] :name :team-size}]]]))
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev}
[:h3 (tr "questions.role")]
[:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
{:label (tr "questions.developer") :value "developer"}
{:label (tr "questions.manager") :value "manager"}
{:label (tr "questions.founder") :value "founder"}
{:label (tr "questions.marketing") :value "marketing"}
{:label (tr "questions.student-teacher") :value "student-teacher"}
{:label (tr "questions.other") :value "other"}]
:name :role
:on-change on-role-change}]
[:div.other
[:label (tr "questions.other")]
[:& fm/input {:name :role-other :label (tr "questions.other") :disabled (not= role "other")}]]
[:h3 (tr "questions.team-size")]
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
{:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
{:label (tr "questions.31-50") :value "31-50" :key "31-50"}
{:label (tr "questions.11-30") :value "11-30" :key "11-30"}
{:label (tr "questions.2-10") :value "2-10" :key "2-10"}
{:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
{:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
:default ""
:name :team-size}]])))
(mf/defc questions (mf/defc questions
[{:keys []}] [{:keys []}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [container (mf/use-ref)
container (mf/use-ref)
step (mf/use-state 1) step (mf/use-state 1)
clean-data (mf/use-state {}) clean-data (mf/use-state {})
@ -336,25 +223,11 @@
(reset! clean-data questionnaire) (reset! clean-data questionnaire)
(st/emit! (du/mark-questions-as-answered questionnaire)))))] (st/emit! (du/mark-questions-as-answered questionnaire)))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)
[:div {:class (stl/css :modal-container) :ref container}
:ref container} (case @step
(case @step 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}] 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}] 3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}] 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]))
4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]
[:div.modal-wrapper.questions-form
[:div.modal-overlay
[:div.modal-container.onboarding.onboarding-v2 {:ref container}
[:img.deco.left {:src "images/deco-left.png" :border 0}]
[:img.deco.right {:src "images/deco-right.png" :border 0}]
[:div.signup-questions
(case @step
1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]]])))

View File

@ -15,7 +15,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
@ -30,64 +29,38 @@
(mf/defc team-modal-right (mf/defc team-modal-right
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :modal-right)}
(if new-css-system [:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.create-team")]
[:div {:class (stl/css :modal-right)} [:p {:class (stl/css :modal-text)}
[:h2 {:class (stl/css :modal-subtitle)} (tr "onboarding.team-modal.create-team-desc")]
(tr "onboarding.team-modal.create-team")] [:ul {:class (stl/css :team-features)}
[:p {:class (stl/css :modal-text)} [:li {:class (stl/css :feature)}
(tr "onboarding.team-modal.create-team-desc")] [:span {:class (stl/css :icon)} i/document-refactor]
[:ul {:class (stl/css :team-features)} [:p {:class (stl/css :modal-text)}
[:li {:class (stl/css :feature)} (tr "onboarding.team-modal.create-team-feature-1")]]
[:span {:class (stl/css :icon)} i/document-refactor] [:li {:class (stl/css :feature)}
[:p {:class (stl/css :modal-text)} [:span {:class (stl/css :icon)} i/move-refactor]
(tr "onboarding.team-modal.create-team-feature-1")]] [:p {:class (stl/css :modal-text)}
[:li {:class (stl/css :feature)} (tr "onboarding.team-modal.create-team-feature-2")]]
[:span {:class (stl/css :icon)} i/move-refactor] [:li {:class (stl/css :feature)}
[:p {:class (stl/css :modal-text)} [:span {:class (stl/css :icon)} i/tree-refactor]
(tr "onboarding.team-modal.create-team-feature-2")]] [:p {:class (stl/css :modal-text)}
[:li {:class (stl/css :feature)} (tr "onboarding.team-modal.create-team-feature-3")]]
[:span {:class (stl/css :icon)} i/tree-refactor] [:li {:class (stl/css :feature)}
[:p {:class (stl/css :modal-text)} [:span {:class (stl/css :icon)} i/user-refactor]
(tr "onboarding.team-modal.create-team-feature-3")]] [:p {:class (stl/css :modal-text)}
[:li {:class (stl/css :feature)} (tr "onboarding.team-modal.create-team-feature-4")]]
[:span {:class (stl/css :icon)} i/user-refactor] [:li {:class (stl/css :feature)}
[:p {:class (stl/css :modal-text)} [:span {:class (stl/css :icon)} i/tick-refactor]
(tr "onboarding.team-modal.create-team-feature-4")]] [:p {:class (stl/css :modal-text)}
[:li {:class (stl/css :feature)} (tr "onboarding.team-modal.create-team-feature-5")]]]])
[:span {:class (stl/css :icon)} i/tick-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-5")]]]]
[:div.team-right
[:h2.subtitle (tr "onboarding.team-modal.create-team")]
[:p.info (tr "onboarding.team-modal.create-team-desc")]
[:ul.team-features
[:li.feature
[:span.icon i/file-html]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-1")]]
[:li.feature
[:span.icon i/pointer-inner]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-2")]]
[:li.feature
[:span.icon i/tree]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-3")]]
[:li.feature
[:span.icon i/user]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-4")]]
[:li.feature
[:span.icon i/tick]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-5")]]]])))
(mf/defc onboarding-team-modal (mf/defc onboarding-team-modal
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :onboarding-team} ::mf/register-as :onboarding-team}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form :spec ::team-form
form (fm/use-form :spec ::team-form
:initial {} :initial {}
:validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space")) :validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space"))
(fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))]) (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))])
@ -109,76 +82,43 @@
teams (mf/deref refs/teams)] teams (mf/deref refs/teams)]
(if new-css-system (if (< (count teams) 2)
(if (< (count teams) 2) [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div.animated.fadeIn {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :modal-left)} [:div {:class (stl/css :first-block)}
[:div {:class (stl/css :first-block)} [:h2 {:class (stl/css :modal-title)}
[:h2 {:class (stl/css :modal-title)} (tr "onboarding.team-modal.create-team")]
(tr "onboarding.team-modal.create-team")] [:p {:class (stl/css :modal-text)}
[:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.create-team-desc")]
(tr "onboarding.choice.team-up.create-team-desc")] [:& fm/form {:form form
[:& fm/form {:form form :class (stl/css :modal-form)
:class (stl/css :modal-form) :on-submit on-submit}
:on-submit on-submit}
[:& fm/input {:type "text" [:& fm/input {:type "text"
:class (stl/css :team-name-input) :class (stl/css :team-name-input)
:name :name :name :name
:placeholder "Team name" :placeholder "Team name"
:label (tr "onboarding.choice.team-up.create-team-placeholder")}] :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:div {:class (stl/css :action-buttons)}
[:& fm/submit-button*
{:className (stl/css :accept-button)
:label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
[:div {:class (stl/css :second-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.choice.team-up.start-without-a-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.start-without-a-team-description")]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :accept-button)
:on-click on-skip}
(tr "onboarding.choice.team-up.continue-without-a-team")]]]]
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "1/2"]]]
(st/emit! (modal/hide)))
(if (< (count teams) 2)
[:div.modal-overlay
[:div.modal-container.onboarding-team.animated.fadeIn
[:div.team-left
[:h2.title (tr "onboarding.team-modal.create-team")]
[:p.info (tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form
:on-submit on-submit}
[:& fm/input {:type "text"
:name :name
:label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:div {:class (stl/css :action-buttons)}
[:& fm/submit-button* [:& fm/submit-button*
{:label (tr "onboarding.choice.team-up.continue-creating-team")}]] {:className (stl/css :accept-button)
:label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
[:div {:class (stl/css :second-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.choice.team-up.start-without-a-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.start-without-a-team-description")]
[:h2.title (tr "onboarding.choice.team-up.start-without-a-team")] [:div {:class (stl/css :action-buttons)}
[:p.info (tr "onboarding.choice.team-up.start-without-a-team-description")] [:button {:class (stl/css :accept-button)
:on-click on-skip}
(tr "onboarding.choice.team-up.continue-without-a-team")]]]]
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "1/2"]]]
[:div (st/emit! (modal/hide)))))
[:button.btn-primary.btn-large {:on-click on-skip} (tr "onboarding.choice.team-up.continue-without-a-team")]]]
[:& team-modal-right]
[:div.paginator "1/2"]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]]
(st/emit! (modal/hide))))))
(defn get-available-roles (defn get-available-roles
[] []
@ -197,8 +137,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :onboarding-team-invitations} ::mf/register-as :onboarding-team-invitations}
[{:keys [name] :as props}] [{:keys [name] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [initial (mf/use-memo (constantly
initial (mf/use-memo (constantly
{:role "editor" {:role "editor"
:name name})) :name name}))
form (fm/use-form :spec ::invite-form form (fm/use-form :spec ::invite-form
@ -265,96 +204,48 @@
(on-invite-now form) (on-invite-now form)
(on-invite-later form)))))] (on-invite-later form)))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div.animated.fadeIn {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :modal-left)} [:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")]
[:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")] [:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
[:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
[:div {:class (stl/css :modal-form)} [:div {:class (stl/css :modal-form)}
[:& fm/form {:form form [:& fm/form {:form form
:on-submit on-submit} :on-submit on-submit}
[:div {:class (stl/css :role-select)} [:div {:class (stl/css :role-select)}
[:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")] [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]] [:& fm/select {:name :role :options roles}]]
[:div {:class (stl/css :invitation-row)} [:div {:class (stl/css :invitation-row)}
[:& fm/multi-input {:type "email" [:& fm/multi-input {:type "email"
:name :emails :name :emails
:auto-focus? true :auto-focus? true
:trim true :trim true
:valid-item-fn us/parse-email :valid-item-fn us/parse-email
:caution-item-fn #{} :caution-item-fn #{}
:label (tr "modals.invite-member.emails") :label (tr "modals.invite-member.emails")
:on-submit on-submit}]]] :on-submit on-submit}]]]
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :back-button) [:button {:class (stl/css :back-button)
:on-click #(st/emit! (modal/show {:type :onboarding-team}) :on-click #(st/emit! (modal/show {:type :onboarding-team})
(ptk/event ::ev/event {::ev/name "invite-members-back" (ptk/event ::ev/event {::ev/name "invite-members-back"
::ev/origin "onboarding" ::ev/origin "onboarding"
:name name :name name
:step 2}))} :step 2}))}
(tr "labels.back")] (tr "labels.back")]
[:& fm/submit-button* [:& fm/submit-button*
{:className (stl/css :accept-button) {:className (stl/css :accept-button)
:label :label
(if (> (count emails) 0) (if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-invite") (tr "onboarding.choice.team-up.create-team-and-invite")
(tr "onboarding.choice.team-up.create-team-without-invite"))}]] (tr "onboarding.choice.team-up.create-team-without-invite"))}]]
[:div {:class (stl/css :modal-hint)} [:div {:class (stl/css :modal-hint)}
(tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]] (tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
[:& team-modal-right] [:& team-modal-right]
[:div {:class (stl/css :paginator)} "2/2"]]] [:div {:class (stl/css :paginator)} "2/2"]]]))
[:div.modal-overlay
[:div.modal-container.onboarding-team-members.animated.fadeIn
[:div.team-left
[:h2.title (tr "onboarding.choice.team-up.invite-members")]
[:p.info (tr "onboarding.choice.team-up.invite-members-info")]
[:& fm/form {:form form
:on-submit on-submit}
[:div.invite-row
[:div.role-wrapper
[:span.rol (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:& fm/multi-input {:type "email"
:name :emails
:auto-focus? true
:trim true
:valid-item-fn us/parse-email
:caution-item-fn #{}
:on-submit on-submit
:label (tr "modals.invite-member.emails")}]]
[:div.buttons
[:button.btn-secondary.btn-large
{:on-click #(st/emit! (modal/show {:type :onboarding-team})
(ptk/event ::ev/event {::ev/name "invite-members-back"
::ev/origin "onboarding"
:name name
:step 2}))}
(tr "labels.back")]
[:& fm/submit-button*
{:label
(if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-send-invites")
(tr "onboarding.choice.team-up.create-team-without-inviting"))}]]
[:div.skip-action
(tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
[:& team-modal-right]
[:div.paginator "2/2"]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))

View File

@ -10,7 +10,6 @@
[app.main.data.dashboard.shortcuts :as sc] [app.main.data.dashboard.shortcuts :as sc]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.settings.access-tokens :refer [access-tokens-page]] [app.main.ui.settings.access-tokens :refer [access-tokens-page]]
[app.main.ui.settings.change-email] [app.main.ui.settings.change-email]
@ -20,7 +19,6 @@
[app.main.ui.settings.password :refer [password-page]] [app.main.ui.settings.password :refer [password-page]]
[app.main.ui.settings.profile :refer [profile-page]] [app.main.ui.settings.profile :refer [profile-page]]
[app.main.ui.settings.sidebar :refer [sidebar]] [app.main.ui.settings.sidebar :refer [sidebar]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -28,21 +26,13 @@
(mf/defc header (mf/defc header
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:header {:class (stl/css :dashboard-header)}
(if new-css-system [:div {:class (stl/css :dashboard-title)}
[:header {:class (stl/css :dashboard-header)} [:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]])
[:div {:class (stl/css :dashboard-title)}
[:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]]
;; OLD
[:header.dashboard-header
[:div.dashboard-title
[:h1 {:data-test "account-title"} (tr "dashboard.your-account-title")]]])))
(mf/defc settings (mf/defc settings
[{:keys [route] :as props}] [{:keys [route] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [section (get-in route [:data :name])
section (get-in route [:data :name])
profile (mf/deref refs/profile) profile (mf/deref refs/profile)
locale (mf/deref i18n/locale)] locale (mf/deref i18n/locale)]
@ -52,53 +42,26 @@
#(when (nil? profile) #(when (nil? profile)
(st/emit! (rt/nav :auth-login)))) (st/emit! (rt/nav :auth-login))))
(if new-css-system [:section {:class (stl/css :dashboard-layout-refactor :dashboard)}
[:section {:class (stl/css :dashboard-layout-refactor :dashboard)} [:& sidebar {:profile profile
[:& sidebar {:profile profile :locale locale
:locale locale :section section}]
:section section}]
[:div {:class (stl/css :dashboard-content)} [:div {:class (stl/css :dashboard-content)}
[:& header] [:& header]
[:section {:class (stl/css :dashboard-container)} [:section {:class (stl/css :dashboard-container)}
(case section (case section
:settings-profile :settings-profile
[:& profile-page {:locale locale}] [:& profile-page {:locale locale}]
:settings-feedback :settings-feedback
[:& feedback-page] [:& feedback-page]
:settings-password :settings-password
[:& password-page {:locale locale}] [:& password-page {:locale locale}]
:settings-options :settings-options
[:& options-page {:locale locale}] [:& options-page {:locale locale}]
:settings-access-tokens :settings-access-tokens
[:& access-tokens-page])]]] [:& access-tokens-page])]]]))
;; OLD
[:section {:class (dom/classnames :dashboard-layout (not new-css-system)
:dashboard-layout-refactor new-css-system)}
[:& sidebar {:profile profile
:locale locale
:section section}]
[:div.dashboard-content
[:& header]
[:section.dashboard-container
(case section
:settings-profile
[:& profile-page {:locale locale}]
:settings-feedback
[:& feedback-page]
:settings-password
[:& password-page {:locale locale}]
:settings-options
[:& options-page {:locale locale}]
:settings-access-tokens
[:& access-tokens-page])]]])))

View File

@ -14,7 +14,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]] [app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -51,8 +50,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :access-token} ::mf/register-as :access-token}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [form (fm/use-form
form (fm/use-form
:initial initial-data :initial initial-data
:spec ::access-token-form :spec ::access-token-form
:validators [name-validator :validators [name-validator
@ -107,176 +105,96 @@
:content (tr "dashboard.access-tokens.copied-success") :content (tr "dashboard.access-tokens.copied-success")
:timeout 1000}))))] :timeout 1000}))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:& fm/form {:form form :on-submit on-submit}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-header)} [:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")] [:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")]
[:button {:class (stl/css :modal-close-btn) [:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]] :on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:type "text" [:& fm/input {:type "text"
:auto-focus? true :auto-focus? true
:form form :form form
:name :name :name :name
:disabled @created? :disabled @created?
:label (tr "modals.create-access-token.name.label") :label (tr "modals.create-access-token.name.label")
:show-success? true :show-success? true
:placeholder (tr "modals.create-access-token.name.placeholder")}]] :placeholder (tr "modals.create-access-token.name.placeholder")}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")] [:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")]
[:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"} [:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
{:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"} {:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
{:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"} {:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
{:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"} {:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
{:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}] {:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
:default "never" :default "never"
:disabled @created? :disabled @created?
:name :expiration-date}] :name :expiration-date}]
(when @created? (when @created?
[:span.token-created-info [:span {:class (stl/css :token-created-info)}
(if (:expires-at created) (if (:expires-at created)
(tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale})) (tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
(tr "dashboard.access-tokens.token-will-not-expire"))])] (tr "dashboard.access-tokens.token-will-not-expire"))])]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
(when @created? (when @created?
[:div {:class (stl/css :custon-input-wrapper)} [:div {:class (stl/css :custon-input-wrapper)}
[:input {:type "text" [:input {:type "text"
:value (:token created "") :value (:token created "")
:class (stl/css :custom-input-token) :class (stl/css :custom-input-token)
:placeholder (tr "modals.create-access-token.token") :placeholder (tr "modals.create-access-token.token")
:read-only true}] :read-only true}]
[:button {:title (tr "modals.create-access-token.copy-token") [:button {:title (tr "modals.create-access-token.copy-token")
:class (stl/css :copy-btn) :class (stl/css :copy-btn)
:on-click copy-token} :on-click copy-token}
i/clipboard-refactor]]) i/clipboard-refactor]])
#_(when @created? #_(when @created?
[:button {:class (stl/css :copy-btn) [:button {:class (stl/css :copy-btn)
:title (tr "modals.create-access-token.copy-token") :title (tr "modals.create-access-token.copy-token")
:on-click copy-token} :on-click copy-token}
[:span {:class (stl/css :token-value)}(:token created "")] [:span {:class (stl/css :token-value)} (:token created "")]
[:span {:class (stl/css :icon)} [:span {:class (stl/css :icon)}
i/clipboard-refactor]])]] i/clipboard-refactor]])]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
(if @created? (if @created?
[:input {:class (stl/css :cancel-button) [:input {:class (stl/css :cancel-button)
:type "button" :type "button"
:value (tr "labels.close") :value (tr "labels.close")
:on-click #(modal/hide!)}] :on-click #(modal/hide!)}]
[:* [:*
[:input {:class (stl/css :cancel-button) [:input {:class (stl/css :cancel-button)
:type "button" :type "button"
:value (tr "labels.cancel") :value (tr "labels.cancel")
:on-click #(modal/hide!)}] :on-click #(modal/hide!)}]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]] {:label (tr "modals.create-access-token.submit-label")}]])]]]]]))
[:div.modal-overlay
[:div.modal-container.access-tokens-modal
[:& fm/form {:form form :on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.create-access-token.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content.generic-form
[:div.fields-container
[:div.fields-row
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:disabled @created?
:label (tr "modals.create-access-token.name.label")
:placeholder (tr "modals.create-access-token.name.placeholder")}]]
[:div.fields-row
[:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
{:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
{:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
{:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
{:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
:label (tr "modals.create-access-token.expiration-date.label")
:default "never"
:disabled @created?
:name :expiration-date}]
(when @created?
[:span.token-created-info
(if (:expires-at created)
(tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
(tr "dashboard.access-tokens.token-will-not-expire"))])]
[:div.fields-row.access-token-created
(when @created?
[:div.custom-input.with-icon
[:input {:type "text"
:value (:token created "")
:placeholder (tr "modals.create-access-token.token")
:read-only true}]
[:button.help-icon {:title (tr "modals.create-access-token.copy-token")
:on-click copy-token}
i/copy]])]]]
[:div.modal-footer
[:div.action-buttons
(if @created?
[:input.cancel-button
{:type "button"
:value (tr "labels.close")
:on-click #(modal/hide!)}]
[:*
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click #(modal/hide!)}]
[:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]])))
(mf/defc access-tokens-hero (mf/defc access-tokens-hero
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))]
on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))] [:div {:class (stl/css :access-tokens-hero-container)}
(if new-css-system [:div {:class (stl/css :access-tokens-hero)}
[:div {:class (stl/css :access-tokens-hero-container)} [:div {:class (stl/css :desc)}
[:div {:class (stl/css :access-tokens-hero)} [:h2 (tr "dashboard.access-tokens.personal")]
[:div {:class (stl/css :desc)} [:p (tr "dashboard.access-tokens.personal.description")]]
[:h2 (tr "dashboard.access-tokens.personal")]
[:p (tr "dashboard.access-tokens.personal.description")]]
[:button [:button
{:class (stl/css :btn-primary) {:class (stl/css :btn-primary)
:on-click on-click} :on-click on-click}
[:span (tr "dashboard.access-tokens.create")]]]] [:span (tr "dashboard.access-tokens.create")]]]]))
;; OLD
[:div.access-tokens-hero-container
[:div.access-tokens-hero
[:div.desc
[:h2 (tr "dashboard.access-tokens.personal")]
[:p (tr "dashboard.access-tokens.personal.description")]]
[:button.btn-primary
{:on-click on-click}
[:span (tr "dashboard.access-tokens.create")]]]])))
(mf/defc access-token-actions (mf/defc access-token-actions
[{:keys [on-delete]}] [{:keys [on-delete]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [local (mf/use-state {:menu-open false})
local (mf/use-state {:menu-open false})
show? (:menu-open @local) show? (:menu-open @local)
options (mf/with-memo [on-delete] options (mf/with-memo [on-delete]
[{:option-name (tr "labels.delete") [{:option-name (tr "labels.delete")
@ -302,47 +220,25 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(on-menu-click event))))] (on-menu-click event))))]
(if new-css-system [:div {:class (stl/css :icon)
[:div :tab-index "0"
{:class (stl/css :icon) :ref menu-ref
:tab-index "0" :on-click on-menu-click
:ref menu-ref :on-key-down on-keydown}
:on-click on-menu-click i/actions
:on-key-down on-keydown} [:& context-menu-a11y
i/actions {:on-close on-menu-close
[:& context-menu-a11y :show show?
{:on-close on-menu-close :fixed? true
:show show? :min-width? true
:fixed? true :top "auto"
:min-width? true :left "auto"
:top "auto" :options options}]]))
:left "auto"
:options options}]]
;; OLD
[:div.icon
{:tab-index "0"
:ref menu-ref
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions
[:& context-menu-a11y
{:on-close on-menu-close
:show show?
:fixed? true
:min-width? true
:top "auto"
:left "auto"
:options options}]])))
(mf/defc access-token-item (mf/defc access-token-item
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [token] :as props}] [{:keys [token] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [locale (mf/deref i18n/locale)
locale (mf/deref i18n/locale)
expires-at (:expires-at token) expires-at (:expires-at token)
expires-txt (some-> expires-at (dt/format-date-locale {:locale locale})) expires-txt (some-> expires-at (dt/format-date-locale {:locale locale}))
expired? (and (some? expires-at) (> (dt/now) expires-at)) expired? (and (some? expires-at) (> (dt/now) expires-at))
@ -366,66 +262,36 @@
:accept-label (tr "modals.delete-acces-token.accept") :accept-label (tr "modals.delete-acces-token.accept")
:on-accept delete-fn}))))] :on-accept delete-fn}))))]
(if new-css-system [:div {:class (stl/css :table-row)}
[:div {:class (stl/css :table-row)} [:div {:class (stl/css :table-field :name)}
[:div {:class (stl/css :table-field :name)} (str (:name token))]
(str (:name token))]
[:div {:class (stl/css :table-field :expiration-date)} [:div {:class (stl/css :table-field :expiration-date)}
[:span {:class (stl/css-case :expired expired? :content true)} [:span {:class (stl/css-case :expired expired? :content true)}
(cond (cond
(nil? expires-at) (tr "dashboard.access-tokens.no-expiration") (nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
expired? (tr "dashboard.access-tokens.expired-on" expires-txt) expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
:else (tr "dashboard.access-tokens.expires-on" expires-txt))]] :else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
[:div {:class (stl/css :table-field :actions)} [:div {:class (stl/css :table-field :actions)}
[:& access-token-actions [:& access-token-actions
{:on-delete on-delete}]]] {:on-delete on-delete}]]]))
;; OLD
[:div.table-row
[:div.table-field.name
(str (:name token))]
[:div.table-field.expiration-date
[:span.content {:class (when expired? "expired")}
(cond
(nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
:else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
[:div.table-field.actions
[:& access-token-actions
{:on-delete on-delete}]]])))
(mf/defc access-tokens-page (mf/defc access-tokens-page
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [tokens (mf/deref tokens-ref)]
tokens (mf/deref tokens-ref)]
(mf/with-effect [] (mf/with-effect []
(dom/set-html-title (tr "title.settings.access-tokens")) (dom/set-html-title (tr "title.settings.access-tokens"))
(st/emit! (du/fetch-access-tokens))) (st/emit! (du/fetch-access-tokens)))
(if new-css-system [:div {:class (stl/css :dashboard-access-tokens)}
[:div {:class (stl/css :dashboard-access-tokens)} [:div
[:div [:& access-tokens-hero]
[:& access-tokens-hero] (if (empty? tokens)
(if (empty? tokens) [:div {:class (stl/css :access-tokens-empty)}
[:div {:class (stl/css :access-tokens-empty)} [:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
[:div (tr "dashboard.access-tokens.empty.no-access-tokens")] [:div (tr "dashboard.access-tokens.empty.add-one")]]
[:div (tr "dashboard.access-tokens.empty.add-one")]] [:div {:class (stl/css :dashboard-table)}
[:div {:class (stl/css :dashboard-table)} [:div {:class (stl/css :table-rows)}
[:div {:class (stl/css :table-rows)} (for [token tokens]
(for [token tokens] [:& access-token-item {:token token :key (:id token)}])]])]]))
[:& access-token-item {:token token :key (:id token)}])]])]]
;; OLD
[:div.dashboard-access-tokens
[:div
[:& access-tokens-hero]
(if (empty? tokens)
[:div.access-tokens-empty
[:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
[:div (tr "dashboard.access-tokens.empty.add-one")]]
[:div.dashboard-table
[:div.table-rows
(for [token tokens]
[:& access-token-item {:token token :key (:id token)}])]])]])))

View File

@ -12,88 +12,6 @@
font-size: $fs-16; font-size: $fs-16;
margin-top: $s-20; margin-top: $s-20;
width: $s-800; width: $s-800;
.table-header {
color: $df-secondary;
display: grid;
font-size: $fs-12;
grid-template-columns: 43% 1fr $s-108 $s-12;
height: $s-40;
max-width: $s-1000;
padding: 0 $s-16;
text-transform: uppercase;
width: 100%;
}
.table-rows {
color: $db-secondary;
display: flex;
flex-direction: column;
margin-top: $s-16;
max-width: $s-1000;
padding-top: 0;
width: 100%;
}
.table-row {
align-items: center;
background-color: $db-tertiary;
border-radius: $br-8;
color: $df-primary;
display: grid;
font-size: $fs-14;
grid-template-columns: 1fr 43% $s-12;
height: fit-content;
min-height: $s-40;
padding: 0 $s-16;
width: 100%;
&:not(:first-child) {
margin-top: $s-8;
}
}
.table-field {
display: flex;
align-items: center;
.icon {
padding-left: $s-12;
cursor: pointer;
}
&.name {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: $df-primary;
display: -webkit-box;
max-width: $s-480;
overflow: hidden;
text-overflow: ellipsis;
}
&.expiration-date {
color: $df-secondary;
font-size: $fs-14;
.content {
padding: $s-2 $s-6;
&.expired {
background-color: var(--warning-color);
border-radius: $br-4;
color: $db-secondary;
}
}
}
&.access-token-created {
word-break: break-all;
}
&.actions {
position: relative;
}
}
svg { svg {
width: $s-12; width: $s-12;
height: $s-12; height: $s-12;
@ -101,6 +19,87 @@
} }
} }
.table-header {
color: $df-secondary;
display: grid;
font-size: $fs-12;
grid-template-columns: 43% 1fr $s-108 $s-12;
height: $s-40;
max-width: $s-1000;
padding: 0 $s-16;
text-transform: uppercase;
width: 100%;
}
.table-rows {
color: $db-secondary;
display: flex;
flex-direction: column;
margin-top: $s-16;
max-width: $s-1000;
padding-top: 0;
width: 100%;
}
.table-row {
align-items: center;
background-color: $db-tertiary;
border-radius: $br-8;
color: $df-primary;
display: grid;
font-size: $fs-14;
grid-template-columns: 1fr 43% $s-12;
height: fit-content;
min-height: $s-40;
padding: 0 $s-16;
width: 100%;
&:not(:first-child) {
margin-top: $s-8;
}
}
.table-field {
display: flex;
align-items: center;
.icon {
padding-left: $s-12;
cursor: pointer;
}
&.name {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: $df-primary;
display: -webkit-box;
max-width: $s-480;
overflow: hidden;
text-overflow: ellipsis;
}
&.expiration-date {
color: $df-secondary;
font-size: $fs-14;
.content {
padding: $s-2 $s-6;
&.expired {
background-color: var(--warning-color);
border-radius: $br-4;
color: $db-secondary;
}
}
}
&.access-token-created {
word-break: break-all;
}
&.actions {
position: relative;
}
}
.dashboard-access-tokens { .dashboard-access-tokens {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -171,75 +170,85 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-container {
@include flexColumn; @extend .modal-container-base;
gap: $s-24; min-width: $s-408;
@include titleTipography; border: $s-1 solid var(--modal-border-color);
margin-bottom: $s-24; }
.fields-row { .modal-header {
@include flexColumn; margin-bottom: $s-24;
.select-title { .modal-title {
@include titleTipography; @include tabTitleTipography;
color: var(--modal-title-foreground-color); color: var(--modal-title-foreground-color);
} }
.custon-input-wrapper { .modal-close-btn {
@include flexRow; @extend .modal-close-btn-base;
border-radius: $br-8;
height: $s-32;
background-color: var(--input-background-color);
}
.custom-input-token {
@extend .input-element;
margin: 0;
flex-grow: 1;
&:focus {
outline: none;
border: $s-1 solid var(--input-border-color-active);
}
}
.token-value {
@include textEllipsis;
@include titleTipography;
flex-grow: 1;
}
.copy-btn {
@include flexCenter;
@extend .button-secondary;
height: $s-28;
width: $s-28;
svg {
@extend .button-icon-small;
}
}
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
}
.cancel-button {
@extend .modal-cancel-btn;
}
}
}
} }
} }
.modal-content {
@include flexColumn;
gap: $s-24;
@include titleTipography;
margin-bottom: $s-24;
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.custon-input-wrapper {
@include flexRow;
border-radius: $br-8;
height: $s-32;
background-color: var(--input-background-color);
}
.custom-input-token {
@extend .input-element;
margin: 0;
flex-grow: 1;
&:focus {
outline: none;
border: $s-1 solid var(--input-border-color-active);
}
}
.token-value {
@include textEllipsis;
@include titleTipography;
flex-grow: 1;
}
.copy-btn {
@include flexCenter;
@extend .button-secondary;
height: $s-28;
width: $s-28;
svg {
@extend .button-icon-small;
}
}
.token-created-info {
color: var(--modal-text-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
}
}
.cancel-button {
@extend .modal-cancel-btn;
}

View File

@ -16,7 +16,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.messages :as msgs] [app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -76,8 +75,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :change-email} ::mf/register-as :change-email}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile (mf/deref refs/profile)
profile (mf/deref refs/profile)
form (fm/use-form :spec ::email-change-form form (fm/use-form :spec ::email-change-form
:validators [email-equality] :validators [email-equality]
:initial profile) :initial profile)
@ -99,82 +97,44 @@
(when (and different-emails-error? (= email-1 email-2)) (when (and different-emails-error? (= email-1 email-2))
(swap! form d/dissoc-in [:errors :email-2])))))] (swap! form d/dissoc-in [:errors :email-2])))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:& fm/form {:form form
[:& fm/form {:form form :on-submit on-submit}
:on-submit on-submit}
[:div {:class (stl/css :modal-header)} [:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title) [:h2 {:class (stl/css :modal-title)
:data-test "change-email-title"} :data-test "change-email-title"}
(tr "modals.change-email.title")] (tr "modals.change-email.title")]
[:button {:class (stl/css :modal-close-btn) [:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]] :on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner [:& msgs/inline-banner
{:type :info {:type :info
:content (tr "modals.change-email.info" (:email profile))}] :content (tr "modals.change-email.info" (:email profile))}]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email" [:& fm/input {:type "email"
:name :email-1 :name :email-1
:label (tr "modals.change-email.new-email") :label (tr "modals.change-email.new-email")
:trim true :trim true
:show-success? true :show-success? true
:on-change-value on-email-change}]] :on-change-value on-email-change}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email" [:& fm/input {:type "email"
:name :email-2 :name :email-2
:label (tr "modals.change-email.confirm-email") :label (tr "modals.change-email.confirm-email")
:trim true :trim true
:show-success? true :show-success? true
:on-change-value on-email-change}]]] :on-change-value on-email-change}]]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons) [:div {:class (stl/css :action-buttons)
:data-test "change-email-submit"} :data-test "change-email-submit"}
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]] {:label (tr "modals.change-email.submit")}]]]]]]
[:div.modal-overlay
[:div.modal-container.change-email-modal.form-container
[:& fm/form {:form form
:on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
[:h2 {:data-test "change-email-title"}
(tr "modals.change-email.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content
[:& msgs/inline-banner
{:type :info
:content (tr "modals.change-email.info" (:email profile))}]
[:div.fields-container
[:div.fields-row
[:& fm/input {:type "email"
:name :email-1
:label (tr "modals.change-email.new-email")
:trim true
:on-change-value on-email-change}]]
[:div.fields-row
[:& fm/input {:type "email"
:name :email-2
:label (tr "modals.change-email.confirm-email")
:trim true
:on-change-value on-email-change}]]]]
[:div.modal-footer
[:div.action-buttons {:data-test "change-email-submit"}
[:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]])
)) ))

View File

@ -8,46 +8,50 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-container {
@include flexColumn; @extend .modal-container-base;
@include titleTipography; min-width: $s-408;
gap: $s-24; border: $s-1 solid var(--modal-border-color);
margin-bottom: $s-24; }
.fields-row { .modal-header {
@include flexColumn; margin-bottom: $s-24;
.select-title { }
@include titleTipography;
color: var(--modal-title-foreground-color);
}
}
}
.modal-footer { .modal-title {
.action-buttons { @include tabTitleTipography;
@extend .modal-action-btns; color: var(--modal-title-foreground-color);
button { }
@extend .modal-accept-btn;
} .modal-close-btn {
.cancel-button { @extend .modal-close-btn-base;
@extend .modal-cancel-btn; }
}
} .modal-content {
} @include flexColumn;
@include titleTipography;
gap: $s-24;
margin-bottom: $s-24;
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
} }
} }
.cancel-button {
@extend .modal-cancel-btn;
}

View File

@ -11,7 +11,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.messages :as msgs] [app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -29,8 +28,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :delete-account} ::mf/register-as :delete-account}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [on-close
on-close
(mf/use-callback #(st/emit! (modal/hide))) (mf/use-callback #(st/emit! (modal/hide)))
on-accept on-accept
@ -39,52 +37,28 @@
(du/request-account-deletion (du/request-account-deletion
(with-meta {} {:on-error on-error}))))] (with-meta {} {:on-error on-error}))))]
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)} [:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")] [:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")]
[:button {:class (stl/css :modal-close-btn) [:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]] :on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner [:& msgs/inline-banner
{:type :warning {:type :warning
:content (tr "modals.delete-account.info")}]] :content (tr "modals.delete-account.info")}]]
[:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :cancel-button) [:button {:class (stl/css :cancel-button)
:on-click on-close} :on-click on-close}
(tr "modals.delete-account.cancel")] (tr "modals.delete-account.cancel")]
[:button {:class (stl/css-case :accept-button true [:button {:class (stl/css-case :accept-button true
:danger true) :danger true)
:on-click on-accept :on-click on-accept
:data-test "delete-account-btn"} :data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")]]]]] (tr "modals.delete-account.confirm")]]]]]))
[:div.modal-overlay
[:div.modal-container.change-email-modal
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.delete-account.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content
[:& msgs/inline-banner
{:type :warning
:content (tr "modals.delete-account.info")}]]
[:div.modal-footer
[:div.action-buttons
[:button.btn-danger.btn-large {:on-click on-accept
:data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")]
[:button.btn-secondary.btn-large {:on-click on-close}
(tr "modals.delete-account.cancel")]]]]])))

View File

@ -8,50 +8,54 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-container {
@include flexColumn; @extend .modal-container-base;
@include titleTipography; min-width: $s-408;
gap: $s-24; border: $s-1 solid var(--modal-border-color);
margin-bottom: $s-24; }
.fields-row { .modal-header {
@include flexColumn; margin-bottom: $s-24;
.select-title { }
@include titleTipography;
color: var(--modal-title-foreground-color);
}
}
}
.modal-footer { .modal-title {
.action-buttons { @include tabTitleTipography;
@extend .modal-action-btns; color: var(--modal-title-foreground-color);
}
.cancel-button { .modal-close-btn {
@extend .modal-cancel-btn; @extend .modal-close-btn-base;
} }
.accept-button {
@extend .modal-accept-btn; .modal-content {
&.danger { @include flexColumn;
@extend .modal-danger-btn; @include titleTipography;
} gap: $s-24;
} margin-bottom: $s-24;
} }
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-button {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
} }
} }

View File

@ -14,7 +14,6 @@
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
@ -29,8 +28,7 @@
(mf/defc feedback-form (mf/defc feedback-form
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile (mf/deref refs/profile)
profile (mf/deref refs/profile)
form (fm/use-form :spec ::feedback-form form (fm/use-form :spec ::feedback-form
:validators [(fm/validate-length :subject fm/max-length-allowed (tr "auth.name.too-long")) :validators [(fm/validate-length :subject fm/max-length-allowed (tr "auth.name.too-long"))
(fm/validate-not-empty :subject (tr "auth.name.not-all-space"))]) (fm/validate-not-empty :subject (tr "auth.name.not-all-space"))])
@ -62,101 +60,54 @@
(->> (rp/cmd! :send-user-feedback data) (->> (rp/cmd! :send-user-feedback data)
(rx/subs! on-succes on-error)))))] (rx/subs! on-succes on-error)))))]
(if new-css-system [:& fm/form {:class (stl/css :feedback-form)
[:& fm/form {:class (stl/css :feedback-form) :on-submit on-submit
:on-submit on-submit :form form}
:form form}
;; --- Feedback section ;; --- Feedback section
[:h2 {:class (stl/css :field-title)} (tr "feedback.title")] [:h2 {:class (stl/css :field-title)} (tr "feedback.title")]
[:p {:class (stl/css :field-text)} (tr "feedback.subtitle")] [:p {:class (stl/css :field-text)} (tr "feedback.subtitle")]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:label (tr "feedback.subject") [:& fm/input {:label (tr "feedback.subject")
:name :subject :name :subject
:show-success? true}]] :show-success? true}]]
[:div {:class (stl/css :fields-row :description)} [:div {:class (stl/css :fields-row :description)}
[:& fm/textarea [:& fm/textarea
{:label (tr "feedback.description") {:label (tr "feedback.description")
:name :content :name :content
:rows 5}]] :rows 5}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (if @loading (tr "labels.sending") (tr "labels.send")) {:label (if @loading (tr "labels.sending") (tr "labels.send"))
:disabled @loading}] :disabled @loading}]
[:hr] [:hr]
[:h2 {:class (stl/css :field-title)} (tr "feedback.discourse-title")] [:h2 {:class (stl/css :field-title)} (tr "feedback.discourse-title")]
[:p {:class (stl/css :field-text)} (tr "feedback.discourse-subtitle1")] [:p {:class (stl/css :field-text)} (tr "feedback.discourse-subtitle1")]
[:a [:a
{:class (stl/css :btn-secondary :btn-large) {:class (stl/css :btn-secondary :btn-large)
:href "https://community.penpot.app" :href "https://community.penpot.app"
:target "_blank"} :target "_blank"}
(tr "feedback.discourse-go-to")] (tr "feedback.discourse-go-to")]
[:hr] [:hr]
[:h2 {:class (stl/css :field-title)} (tr "feedback.twitter-title")] [:h2 {:class (stl/css :field-title)} (tr "feedback.twitter-title")]
[:p {:class (stl/css :field-text)} (tr "feedback.twitter-subtitle1")] [:p {:class (stl/css :field-text)} (tr "feedback.twitter-subtitle1")]
[:a [:a
{:class (stl/css :btn-secondary :btn-large) {:class (stl/css :btn-secondary :btn-large)
:href "https://twitter.com/penpotapp" :href "https://twitter.com/penpotapp"
:target "_blank"} :target "_blank"}
(tr "feedback.twitter-go-to")]] (tr "feedback.twitter-go-to")]]))
;; OLD
[:& fm/form {:class "feedback-form"
:on-submit on-submit
:form form}
;; --- Feedback section
[:h2.field-title (tr "feedback.title")]
[:p.field-text (tr "feedback.subtitle")]
[:div.fields-row
[:& fm/input {:label (tr "feedback.subject")
:name :subject}]]
[:div.fields-row
[:& fm/textarea
{:label (tr "feedback.description")
:name :content
:rows 5}]]
[:> fm/submit-button*
{:label (if @loading (tr "labels.sending") (tr "labels.send"))
:disabled @loading}]
[:hr]
[:h2.field-title (tr "feedback.discourse-title")]
[:p.field-text (tr "feedback.discourse-subtitle1")]
[:a.btn-secondary.btn-large
{:href "https://community.penpot.app" :target "_blank"}
(tr "feedback.discourse-go-to")]
[:hr]
[:h2.field-title (tr "feedback.twitter-title")]
[:p.field-text (tr "feedback.twitter-subtitle1")]
[:a.btn-secondary.btn-large
{:href "https://twitter.com/penpotapp" :target "_blank"}
(tr "feedback.twitter-go-to")]])))
(mf/defc feedback-page (mf/defc feedback-page
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (mf/use-effect
(mf/use-effect #(dom/set-html-title (tr "title.settings.feedback")))
#(dom/set-html-title (tr "title.settings.feedback")))
(if new-css-system [:div {:class (stl/css :dashboard-settings)}
[:div {:class (stl/css :dashboard-settings)} [:div {:class (stl/css :form-container)}
[:div {:class (stl/css :form-container)} [:& feedback-form]]])
[:& feedback-form]]]
;; OLD
[:div.dashboard-settings
[:div.form-container
[:& feedback-form]]])))

View File

@ -13,7 +13,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -38,78 +37,49 @@
(mf/defc options-form (mf/defc options-form
{::mf/wrap-props false} {::mf/wrap-props false}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile (mf/deref refs/profile)
profile (mf/deref refs/profile)
initial (mf/with-memo [profile] initial (mf/with-memo [profile]
(update profile :lang #(or % ""))) (update profile :lang #(or % "")))
form (fm/use-form :spec ::options-form form (fm/use-form :spec ::options-form
:initial initial)] :initial initial)]
(if new-css-system [:& fm/form {:class (stl/css :options-form)
[:& fm/form {:class (stl/css :options-form) :on-submit on-submit
:on-submit on-submit :form form}
:form form}
[:h3 (tr "labels.language")] [:h3 (tr "labels.language")]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/select {:options (into [{:label "Auto (browser)" :value ""}] [:& fm/select {:options (into [{:label "Auto (browser)" :value ""}]
i18n/supported-locales) i18n/supported-locales)
:label (tr "dashboard.select-ui-language") :label (tr "dashboard.select-ui-language")
:default "" :default ""
:name :lang :name :lang
:data-test "setting-lang"}]] :data-test "setting-lang"}]]
[:h3 (tr "dashboard.theme-change")] [:h3 (tr "dashboard.theme-change")]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/select {:label (tr "dashboard.select-ui-theme") [:& fm/select {:label (tr "dashboard.select-ui-theme")
:name :theme :name :theme
:default "default" :default "default"
:options [{:label "Penpot Dark (default)" :value "default"} :options [{:label "Penpot Dark (default)" :value "default"}
{:label "Penpot Light" :value "light"}] {:label "Penpot Light" :value "light"}]
:data-test "setting-theme"}]] :data-test "setting-theme"}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "dashboard.update-settings") {:label (tr "dashboard.update-settings")
:data-test "submit-lang-change" :data-test "submit-lang-change"
:class (stl/css :btn-primary)}]] :class (stl/css :btn-primary)}]]))
;; OLD
[:& fm/form {:class "options-form"
:on-submit on-submit
:form form}
[:h2 (tr "labels.language")]
[:div.fields-row
[:& fm/select {:options (into [{:label "Auto (browser)" :value ""}]
i18n/supported-locales)
:label (tr "dashboard.select-ui-language")
:default ""
:name :lang
:data-test "setting-lang"}]]
[:> fm/submit-button*
{:label (tr "dashboard.update-settings")
:data-test "submit-lang-change"}]])))
;; --- Password Page ;; --- Password Page
(mf/defc options-page (mf/defc options-page
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (mf/use-effect
(mf/use-effect #(dom/set-html-title (tr "title.settings.options")))
#(dom/set-html-title (tr "title.settings.options")))
(if new-css-system [:div {:class (stl/css :dashboard-settings)}
[:div {:class (stl/css :dashboard-settings)} [:div {:class (stl/css :form-container) :data-test "settings-form"}
[:div {:class (stl/css :form-container) :data-test "settings-form"} [:h2 (tr "labels.settings")]
[:h2 (tr "labels.settings")] [:& options-form {}]]])
[:& options-form {}]]]
;; OLD
[:div.dashboard-settings
[:div.form-container
{:data-test "settings-form"}
[:& options-form {}]]])))

View File

@ -12,7 +12,6 @@
[app.main.data.users :as udu] [app.main.data.users :as udu]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t tr]] [app.util.i18n :as i18n :refer [t tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -71,88 +70,51 @@
(mf/defc password-form (mf/defc password-form
[{:keys [locale] :as props}] [{:keys [locale] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [initial (mf/use-memo (constantly {:password-old nil}))
initial (mf/use-memo (constantly {:password-old nil}))
form (fm/use-form :spec ::password-form form (fm/use-form :spec ::password-form
:validators [(fm/validate-not-all-spaces :password-old (tr "auth.password-not-empty")) :validators [(fm/validate-not-all-spaces :password-old (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-1 (tr "auth.password-not-empty")) (fm/validate-not-empty :password-1 (tr "auth.password-not-empty"))
(fm/validate-not-empty :password-2 (tr "auth.password-not-empty")) (fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))
password-equality] password-equality]
:initial initial)] :initial initial)]
(if new-css-system [:& fm/form {:class (stl/css :password-form)
[:& fm/form {:class (stl/css :password-form) :on-submit on-submit
:on-submit on-submit :form form}
:form form}
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input [:& fm/input
{:type "password" {:type "password"
:name :password-old :name :password-old
:auto-focus? true :auto-focus? true
:label (t locale "labels.old-password")}]] :label (t locale "labels.old-password")}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input [:& fm/input
{:type "password" {:type "password"
:name :password-1 :name :password-1
:show-success? true :show-success? true
:label (t locale "labels.new-password")}]] :label (t locale "labels.new-password")}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input [:& fm/input
{:type "password" {:type "password"
:name :password-2 :name :password-2
:show-success? true :show-success? true
:label (t locale "labels.confirm-password")}]] :label (t locale "labels.confirm-password")}]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (t locale "dashboard.update-settings") {:label (t locale "dashboard.update-settings")
:data-test "submit-password" :data-test "submit-password"
:class (stl/css :update-btn)}]] :class (stl/css :update-btn)}]]))
;; OLD
[:& fm/form {:class "password-form"
:on-submit on-submit
:form form}
[:h2 (t locale "dashboard.password-change")]
[:div.fields-row
[:& fm/input
{:type "password"
:name :password-old
:auto-focus? true
:label (t locale "labels.old-password")}]]
[:div.fields-row
[:& fm/input
{:type "password"
:name :password-1
:label (t locale "labels.new-password")}]]
[:div.fields-row
[:& fm/input
{:type "password"
:name :password-2
:label (t locale "labels.confirm-password")}]]
[:> fm/submit-button*
{:label (t locale "dashboard.update-settings")
:data-test "submit-password"}]])))
;; --- Password Page ;; --- Password Page
(mf/defc password-page (mf/defc password-page
[{:keys [locale]}] [{:keys [locale]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (mf/use-effect
(mf/use-effect #(dom/set-html-title (tr "title.settings.password")))
#(dom/set-html-title (tr "title.settings.password")))
(if new-css-system [:section {:class (stl/css :dashboard-settings)}
[:section {:class (stl/css :dashboard-settings)} [:div {:class (stl/css :form-container)}
[:div {:class (stl/css :form-container)} [:h2 (t locale "dashboard.password-change")]
[:h2 (t locale "dashboard.password-change")] [:& password-form {:locale locale}]]])
[:& password-form {:locale locale}]]]
;; old
[:section.dashboard-settings.form-container
[:div.form-container
[:& password-form {:locale locale}]]])))

View File

@ -16,8 +16,6 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -43,9 +41,7 @@
(mf/defc profile-form (mf/defc profile-form
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile (mf/deref refs/profile)
profile (mf/deref refs/profile)
form (fm/use-form :spec ::profile-form form (fm/use-form :spec ::profile-form
:initial profile :initial profile
:validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long")) :validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))
@ -59,78 +55,43 @@
(mf/use-callback (mf/use-callback
#(modal/show! :delete-account {}))] #(modal/show! :delete-account {}))]
(if new-css-system [:& fm/form {:on-submit on-submit
[:& fm/form {:on-submit on-submit :form form
:form form :class (stl/css :profile-form)}
:class (stl/css :profile-form)} [:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :fields-row)} [:& fm/input
[:& fm/input {:type "text"
{:type "text" :name :fullname
:name :fullname :label (tr "dashboard.your-name")}]]
:label (tr "dashboard.your-name")}]]
[:div {:class (stl/css :fields-row) [:div {:class (stl/css :fields-row)
:on-click handle-show-change-email} :on-click handle-show-change-email}
[:& fm/input [:& fm/input
{:type "email" {:type "email"
:name :email :name :email
:disabled true :disabled true
:label (tr "dashboard.your-email")}] :label (tr "dashboard.your-email")}]
[:div {:class (stl/css :options)} [:div {:class (stl/css :options)}
[:div.change-email [:div.change-email
[:a {:on-click handle-show-change-email} [:a {:on-click handle-show-change-email}
(tr "dashboard.change-email")]]]] (tr "dashboard.change-email")]]]]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "dashboard.save-settings") {:label (tr "dashboard.save-settings")
:disabled (empty? (:touched @form)) :disabled (empty? (:touched @form))
:className (stl/css :btn-primary)}] :className (stl/css :btn-primary)}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-item)} [:div {:class (stl/css :link-item)}
[:a {:on-click handle-show-delete-account [:a {:on-click handle-show-delete-account
:data-test "remove-acount-btn"} :data-test "remove-acount-btn"}
(tr "dashboard.remove-account")]]]] (tr "dashboard.remove-account")]]]]))
;; OLD
[:& fm/form {:on-submit on-submit
:form form
:class "profile-form"}
[:div.fields-row
[:& fm/input
{:type "text"
:name :fullname
:label (tr "dashboard.your-name")}]]
[:div.fields-row
[:& fm/input
{:type "email"
:name :email
:disabled true
:help-icon i/at
:label (tr "dashboard.your-email")}]
[:div.options
[:div.change-email
[:a {:on-click #(modal/show! :change-email {})}
(tr "dashboard.change-email")]]]]
[:> fm/submit-button*
{:label (tr "dashboard.save-settings")
:disabled (empty? (:touched @form))}]
[:div.links
[:div.link-item
[:a {:on-click #(modal/show! :delete-account {})
:data-test "remove-acount-btn"}
(tr "dashboard.remove-account")]]]])))
;; --- Profile Photo Form ;; --- Profile Photo Form
(mf/defc profile-photo-form [] (mf/defc profile-photo-form []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [file-input (mf/use-ref nil)
file-input (mf/use-ref nil)
profile (mf/deref refs/profile) profile (mf/deref refs/profile)
photo (cf/resolve-profile-photo-url profile) photo (cf/resolve-profile-photo-url profile)
on-image-click #(dom/click (mf/ref-val file-input)) on-image-click #(dom/click (mf/ref-val file-input))
@ -139,44 +100,25 @@
(fn [file] (fn [file]
(st/emit! (du/update-photo file)))] (st/emit! (du/update-photo file)))]
(if new-css-system [:form {:class (stl/css :avatar-form)}
[:form {:class (stl/css :avatar-form)} [:div {:class (stl/css :image-change-field)}
[:div {:class (stl/css :image-change-field)} [:span {:class (stl/css :update-overlay)
[:span {:class (stl/css :update-overlay) :on-click on-image-click} (tr "labels.update")]
:on-click on-image-click} (tr "labels.update")] [:img {:src photo}]
[:img {:src photo}] [:& file-uploader {:accept "image/jpeg,image/png"
[:& file-uploader {:accept "image/jpeg,image/png" :multi false
:multi false :ref file-input
:ref file-input :on-selected on-file-selected
:on-selected on-file-selected :data-test "profile-image-input"}]]]))
:data-test "profile-image-input"}]]]
;; OLD
[:form.avatar-form
[:div.image-change-field
[:span.update-overlay {:on-click on-image-click} (tr "labels.update")]
[:img {:src photo}]
[:& file-uploader {:accept "image/jpeg,image/png"
:multi false
:ref file-input
:on-selected on-file-selected
:data-test "profile-image-input"}]]])))
;; --- Profile Page ;; --- Profile Page
(mf/defc profile-page [] (mf/defc profile-page []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (mf/with-effect []
(mf/with-effect [] (dom/set-html-title (tr "title.settings.profile")))
(dom/set-html-title (tr "title.settings.profile"))) [:div {:class (stl/css :dashboard-settings)}
(if new-css-system [:div {:class (stl/css :form-container)}
[:div {:class (stl/css :dashboard-settings)} [:h2 (tr "labels.profile")]
[:div {:class (stl/css :form-container)} [:& profile-photo-form]
[:h2 (tr "labels.profile")] [:& profile-form]]])
[:& profile-photo-form]
[:& profile-form]]]
;; OLD
[:div.dashboard-settings
[:div.form-container.two-columns
[:& profile-photo-form]
[:& profile-form]]])))

View File

@ -12,7 +12,6 @@
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.sidebar :refer [profile-section]] [app.main.ui.dashboard.sidebar :refer [profile-section]]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -23,8 +22,7 @@
(mf/defc sidebar-content (mf/defc sidebar-content
[{:keys [profile section] :as props}] [{:keys [profile section] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile? (= section :settings-profile)
profile? (= section :settings-profile)
password? (= section :settings-password) password? (= section :settings-password)
options? (= section :settings-options) options? (= section :settings-options)
feedback? (= section :settings-feedback) feedback? (= section :settings-feedback)
@ -69,107 +67,52 @@
(st/emit! (modal/show {:type :onboarding})) (st/emit! (modal/show {:type :onboarding}))
(st/emit! (modal/show {:type :release-notes :version version}))))))] (st/emit! (modal/show {:type :release-notes :version version}))))))]
(if new-css-system [:div {:class (stl/css :sidebar-content)}
[:div {:class (stl/css :sidebar-content)} [:div {:class (stl/css :sidebar-content-section)}
[:div {:class (stl/css :sidebar-content-section)} [:div {:class (stl/css :back-to-dashboard)
[:div {:class (stl/css :back-to-dashboard) :on-click go-dashboard}
:on-click go-dashboard} [:span {:class (stl/css :icon)} i/arrow-down]
[:span {:class (stl/css :icon)} i/arrow-down] [:span {:class (stl/css :text)} (tr "labels.dashboard")]]]
[:span {:class (stl/css :text)} (tr "labels.dashboard")]]] [:hr]
[:div {:class (stl/css :sidebar-content-section)}
[:ul {:class (stl/css :sidebar-nav :no-overflow)}
[:li {:class (when profile? (stl/css :current))
:on-click go-settings-profile}
[:span {:class (stl/css :element-title)} (tr "labels.profile")]]
[:li {:class (when password? (stl/css :current))
:on-click go-settings-password}
[:span {:class (stl/css :element-title)} (tr "labels.password")]]
[:li {:class (when options? (stl/css :current))
:on-click go-settings-options
:data-test "settings-profile"}
[:span {:class (stl/css :element-title)} (tr "labels.settings")]]
(when (contains? cf/flags :access-tokens)
[:li {:class (when access-tokens? (stl/css :current))
:on-click go-settings-access-tokens
:data-test "settings-access-tokens"}
[:span {:class (stl/css :element-title)} (tr "labels.access-tokens")]])
[:hr] [:hr]
[:div {:class (stl/css :sidebar-content-section)} [:li {:on-click show-release-notes :data-test "release-notes"}
[:ul {:class (stl/css :sidebar-nav :no-overflow)} [:span {:class (stl/css :element-title)} (tr "labels.release-notes")]]
[:li {:class (when profile? (stl/css :current))
:on-click go-settings-profile}
[:span {:class (stl/css :element-title)} (tr "labels.profile")]]
[:li {:class (when password? (stl/css :current)) (when (contains? cf/flags :user-feedback)
:on-click go-settings-password} [:li {:class (when feedback? (stl/css :current))
[:span {:class (stl/css :element-title)} (tr "labels.password")]] :on-click go-settings-feedback}
i/msg-info
[:li {:class (when options? (stl/css :current)) [:span {:class (stl/css :element-title)} (tr "labels.give-feedback")]])]]]))
:on-click go-settings-options
:data-test "settings-profile"}
[:span {:class (stl/css :element-title)} (tr "labels.settings")]]
(when (contains? cf/flags :access-tokens)
[:li {:class (when access-tokens? (stl/css :current))
:on-click go-settings-access-tokens
:data-test "settings-access-tokens"}
[:span {:class (stl/css :element-title)} (tr "labels.access-tokens")]])
[:hr]
[:li {:on-click show-release-notes :data-test "release-notes"}
[:span {:class (stl/css :element-title)} (tr "labels.release-notes")]]
(when (contains? cf/flags :user-feedback)
[:li {:class (when feedback? (stl/css :current))
:on-click go-settings-feedback}
i/msg-info
[:span {:class (stl/css :element-title)} (tr "labels.give-feedback")]])]]]
;; OLD
[:div.sidebar-content
[:div.sidebar-content-section
[:div.back-to-dashboard {:on-click go-dashboard}
[:span.icon i/arrow-down]
[:span.text (tr "labels.dashboard")]]]
[:hr]
[:div.sidebar-content-section
[:ul.sidebar-nav.no-overflow
[:li {:class (when profile? "current")
:on-click go-settings-profile}
i/user
[:span.element-title (tr "labels.profile")]]
[:li {:class (when password? "current")
:on-click go-settings-password}
i/lock
[:span.element-title (tr "labels.password")]]
[:li {:class (when options? "current")
:on-click go-settings-options
:data-test "settings-profile"}
i/tree
[:span.element-title (tr "labels.settings")]]
(when (contains? cf/flags :access-tokens)
[:li {:class (when access-tokens? "current")
:on-click go-settings-access-tokens
:data-test "settings-access-tokens"}
i/icon-key
[:span.element-title (tr "labels.access-tokens")]])
[:hr]
[:li {:on-click show-release-notes :data-test "release-notes"}
i/pencil
[:span.element-title (tr "labels.release-notes")]]
(when (contains? cf/flags :user-feedback)
[:li {:class (when feedback? "current")
:on-click go-settings-feedback}
i/msg-info
[:span.element-title (tr "labels.give-feedback")]])]]])))
(mf/defc sidebar (mf/defc sidebar
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [profile locale section]}] [{:keys [profile locale section]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:div {:class (stl/css :dashboard-sidebar :settings)}
(if new-css-system [:& sidebar-content {:profile profile
[:div {:class (stl/css :dashboard-sidebar :settings)} :section section}]
[:& sidebar-content {:profile profile [:& profile-section {:profile profile
:section section}] :locale locale}]])
[:& profile-section {:profile profile
:locale locale}]]
;; OLD
[:div.dashboard-sidebar.settings
[:& sidebar-content {:profile profile
:section section}]
[:& profile-section {:profile profile
:locale locale}]])))

View File

@ -20,112 +20,64 @@
(mf/defc static-header (mf/defc static-header
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [children (obj/get props "children")
children (obj/get props "children")
on-click (mf/use-callback #(set! (.-href globals/location) "/"))] on-click (mf/use-callback #(set! (.-href globals/location) "/"))]
(if new-css-system [:section {:class (stl/css :exception-layout)}
[:section {:class (stl/css :exception-layout)} [:button
[:button {:class (stl/css :exception-header)
{:class (stl/css :exception-header) :on-click on-click}
:on-click on-click} i/logo-icon]
i/logo-icon] [:div {:class (stl/css :deco-before)} i/logo-error-screen]
[:div {:class (stl/css :deco-before)} i/logo-error-screen]
[:div {:class (stl/css :exception-content)} [:div {:class (stl/css :exception-content)}
[:div {:class (stl/css :container)} children]] [:div {:class (stl/css :container)} children]]
[:div {:class (stl/css :deco-after)} i/logo-error-screen]] [:div {:class (stl/css :deco-after)} i/logo-error-screen]]))
[:section.exception-layout
[:div.exception-header
{:on-click on-click}
i/logo]
[:div.exception-content
[:div.container children]]])))
(mf/defc invalid-token (mf/defc invalid-token
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:> static-header {}
(if new-css-system [:div {:class (stl/css :main-message)} (tr "errors.invite-invalid")]
[:> static-header {} [:div {:class (stl/css :desc-message)} (tr "errors.invite-invalid.info")]])
[:div {:class (stl/css :main-message)} (tr "errors.invite-invalid")]
[:div {:class (stl/css :desc-message)} (tr "errors.invite-invalid.info")]]
[:> static-header {}
[:div.image i/unchain]
[:div.main-message (tr "errors.invite-invalid")]
[:div.desc-message (tr "errors.invite-invalid.info")]])))
(mf/defc not-found (mf/defc not-found
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] [:> static-header {}
(if new-css-system [:div {:class (stl/css :main-message)} (tr "labels.not-found.main-message")]
[:> static-header {} [:div {:class (stl/css :desc-message)} (tr "labels.not-found.desc-message")]])
[:div {:class (stl/css :main-message)} (tr "labels.not-found.main-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.not-found.desc-message")]]
[:> static-header {}
[:div.image i/icon-empty]
[:div.main-message (tr "labels.not-found.main-message")]
[:div.desc-message (tr "labels.not-found.desc-message")]])))
(mf/defc bad-gateway (mf/defc bad-gateway
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [handle-retry
handle-retry
(mf/use-callback (mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))] (fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system [:> static-header {}
[:> static-header {} [:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")]
[:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")] [:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")] [:div {:class (stl/css :sign-info)}
[:div {:class (stl/css :sign-info)} [:button {:on-click handle-retry} (tr "labels.retry")]]]))
[:button {:on-click handle-retry} (tr "labels.retry")]]]
[:> static-header {}
[:div.image i/icon-empty]
[:div.main-message (tr "labels.bad-gateway.main-message")]
[:div.desc-message (tr "labels.bad-gateway.desc-message")]
[:div.sign-info
[:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
(mf/defc service-unavailable (mf/defc service-unavailable
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [handle-retry
handle-retry
(mf/use-callback (mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))] (fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system [:> static-header {}
[:> static-header {} [:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")]
[:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")] [:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")] [:div {:class (stl/css :sign-info)}
[:div {:class (stl/css :sign-info)} [:button {:on-click handle-retry} (tr "labels.retry")]]]))
[:button {:on-click handle-retry} (tr "labels.retry")]]]
[:> static-header {}
[:div.main-message (tr "labels.service-unavailable.main-message")]
[:div.desc-message (tr "labels.service-unavailable.desc-message")]
[:div.sign-info
[:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
(mf/defc internal-error (mf/defc internal-error
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [handle-retry
handle-retry
(mf/use-callback (mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))] (fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system [:> static-header {}
[:> static-header {} [:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")]
[:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")] [:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")] [:div {:class (stl/css :sign-info)}
[:div {:class (stl/css :sign-info)} [:button {:on-click handle-retry} (tr "labels.retry")]]]))
[:button {:on-click handle-retry} (tr "labels.retry")]]]
[:> static-header {}
[:div.image i/icon-empty]
[:div.main-message (tr "labels.internal-error.main-message")]
[:div.desc-message (tr "labels.internal-error.desc-message")]
[:div.sign-info
[:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
(mf/defc exception-page (mf/defc exception-page
[{:keys [data] :as props}] [{:keys [data] :as props}]

View File

@ -8,7 +8,6 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.viewer.inspect.annotation :refer [annotation]] [app.main.ui.viewer.inspect.annotation :refer [annotation]]
[app.main.ui.viewer.inspect.attributes.blur :refer [blur-panel]] [app.main.ui.viewer.inspect.attributes.blur :refer [blur-panel]]
@ -36,65 +35,35 @@
(mf/defc attributes (mf/defc attributes
[{:keys [page-id file-id shapes frame from libraries share-id objects]}] [{:keys [page-id file-id shapes frame from libraries share-id objects]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [shapes (hooks/use-equal-memo shapes)
shapes (hooks/use-equal-memo shapes)
type (if (= (count shapes) 1) (-> shapes first :type) :multiple) type (if (= (count shapes) 1) (-> shapes first :type) :multiple)
options (type->options type) options (type->options type)
content (when (= (count shapes) 1) content (when (= (count shapes) 1)
(ctkl/get-component-annotation (first shapes) libraries))] (ctkl/get-component-annotation (first shapes) libraries))]
(if new-css-system [:div {:class (stl/css :element-options)}
[:div {:class (stl/css :element-options)} (for [[idx option] (map-indexed vector options)]
(for [[idx option] (map-indexed vector options)] [:> (case option
[:> (case option :geometry geometry-panel
:geometry geometry-panel :layout layout-panel
:layout layout-panel :layout-element layout-element-panel
:layout-element layout-element-panel :fill fill-panel
:fill fill-panel :stroke stroke-panel
:stroke stroke-panel :shadow shadow-panel
:shadow shadow-panel :blur blur-panel
:blur blur-panel :image image-panel
:image image-panel :text text-panel
:text text-panel :svg svg-panel)
:svg svg-panel) {:key idx
{:key idx :shapes shapes
:shapes shapes :objects objects
:objects objects :frame frame
:frame frame :from from}])
:from from}]) (when content
(when content [:& annotation {:content content}])
[:& annotation {:content content}]) [:& exports
[:& exports {:shapes shapes
{:shapes shapes :type type
:type type :page-id page-id
:page-id page-id :file-id file-id
:file-id file-id :share-id share-id}]]))
:share-id share-id}]]
[:div.element-options
(for [[idx option] (map-indexed vector options)]
[:> (case option
:geometry geometry-panel
:layout layout-panel
:layout-element layout-element-panel
:fill fill-panel
:stroke stroke-panel
:shadow shadow-panel
:blur blur-panel
:image image-panel
:text text-panel
:svg svg-panel)
{:key idx
:shapes shapes
:objects objects
:frame frame
:from from}])
(when content
[:& annotation {:content content}])
[:& exports
{:shapes shapes
:type type
:page-id page-id
:file-id file-id
:share-id share-id}]])))

View File

@ -20,7 +20,6 @@
[app.main.ui.components.code-block :refer [code-block]] [app.main.ui.components.code-block :refer [code-block]]
[app.main.ui.components.copy-button :refer [copy-button]] [app.main.ui.components.copy-button :refer [copy-button]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.hooks.resize :refer [use-resize-hook]] [app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
@ -100,8 +99,7 @@
(mf/defc code (mf/defc code
[{:keys [shapes frame on-expand from]}] [{:keys [shapes frame on-expand from]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [style-type* (mf/use-state "css")
style-type* (mf/use-state "css")
markup-type* (mf/use-state "html") markup-type* (mf/use-state "html")
fontfaces-css* (mf/use-state nil) fontfaces-css* (mf/use-state nil)
images-data* (mf/use-state nil) images-data* (mf/use-state nil)
@ -232,135 +230,80 @@
(fn [result] (fn [result]
(reset! images-data* result))))) (reset! images-data* result)))))
(if new-css-system [:div {:class (stl/css :element-options)}
[:div {:class (stl/css :element-options)} [:div {:class (stl/css :attributes-block)}
[:div {:class (stl/css :attributes-block)} [:button {:class (stl/css :download-button)
[:button {:class (stl/css :download-button) :on-click handle-copy-all-code}
:on-click handle-copy-all-code} "Copy all code"]]
"Copy all code"]]
#_[:div.attributes-block #_[:div.attributes-block
[:button.download-button {:on-click handle-open-review} [:button.download-button {:on-click handle-open-review}
"Preview"]] "Preview"]]
[:div {:class (stl/css :code-block)} [:div {:class (stl/css :code-block)}
[:div {:class (stl/css :code-row-lang)} [:div {:class (stl/css :code-row-lang)}
[:button {:class (stl/css :toggle-btn) [:button {:class (stl/css :toggle-btn)
:data-type "css" :data-type "css"
:on-click handle-collapse} :on-click handle-collapse}
[:span {:class (stl/css-case [:span {:class (stl/css-case
:collapsabled-icon true :collapsabled-icon true
:rotated collapsed-css?)} :rotated collapsed-css?)}
i/arrow-refactor]] i/arrow-refactor]]
[:& select {:default-value style-type [:& select {:default-value style-type
:class (stl/css :code-lang-select) :class (stl/css :code-lang-select)
:options [{:label "CSS" :value "css"}]}] :on-change set-style
:options [{:label "CSS" :value "css"}]}]
[:div {:class (stl/css :action-btns)} [:div {:class (stl/css :action-btns)}
[:button {:class (stl/css :expand-button) [:button {:class (stl/css :expand-button)
:on-click on-expand} :on-click on-expand}
i/code-refactor] i/code-refactor]
[:& copy-button {:data #(replace-map style-code images-data) [:& copy-button {:data #(replace-map style-code images-data)
:on-copied on-style-copied}]]] :on-copied on-style-copied}]]]
(when-not collapsed-css? (when-not collapsed-css?
[:div {:class (stl/css :code-row-display) [:div {:class (stl/css :code-row-display)
:style #js {"--code-height" (str (or style-size 400) "px")}} :style #js {"--code-height" (str (or style-size 400) "px")}}
[:& code-block {:type style-type
:code style-code}]])
[:div {:class (stl/css :resize-area)
:on-pointer-down on-style-pointer-down
:on-lost-pointer-capture on-style-lost-pointer-capture
:on-pointer-move on-style-pointer-move}]]
[:div {:class (stl/css :code-block)}
[:div {:class (stl/css :code-row-lang)}
[:button {:class (stl/css :toggle-btn)
:data-type "markup"
:on-click handle-collapse}
[:span {:class (stl/css-case
:collapsabled-icon true
:rotated collapsed-markup?)}
i/arrow-refactor]]
[:& select {:default-value markup-type
:class (stl/css :code-lang-select)
:options [{:label "HTML" :value "html"}
{:label "SVG" :value "svg"}]
:on-change set-markup}]
[:div {:class (stl/css :action-btns)}
[:button {:class (stl/css :expand-button)
:on-click on-expand}
i/code-refactor]
[:& copy-button {:data #(replace-map markup-code images-data)
:on-copied on-markup-copied}]]]
(when-not collapsed-markup?
[:div {:class (stl/css :code-row-display)
:style #js {"--code-height" (str (or markup-size 400) "px")}}
[:& code-block {:type markup-type
:code markup-code}]])
[:div {:class (stl/css :resize-area)
:on-pointer-down on-markup-pointer-down
:on-lost-pointer-capture on-markup-lost-pointer-capture
:on-pointer-move on-markup-pointer-move}]]]
[:div.element-options
[:div.attributes-block
[:button.download-button {:on-click handle-copy-all-code}
"Copy all code"]]
#_[:div.attributes-block
[:button.download-button {:on-click handle-open-review}
"Preview"]]
[:div.code-block
[:div.code-row-lang
[:& select {:default-value style-type
:class "custom-select"
:options [{:label "CSS" :value "css"}]
:on-change set-style}]
[:button.expand-button
{:on-click on-expand}
i/full-screen]
[:& copy-button {:data #(replace-map style-code images-data)
:on-copied on-style-copied}]]
[:div.code-row-display {:style #js {"--code-height" (str (or style-size 400) "px")}}
[:& code-block {:type style-type [:& code-block {:type style-type
:code style-code}]] :code style-code}]])
[:div.resize-area {:on-pointer-down on-style-pointer-down [:div {:class (stl/css :resize-area)
:on-lost-pointer-capture on-style-lost-pointer-capture :on-pointer-down on-style-pointer-down
:on-pointer-move on-style-pointer-move}]] :on-lost-pointer-capture on-style-lost-pointer-capture
:on-pointer-move on-style-pointer-move}]]
[:div.code-block [:div {:class (stl/css :code-block)}
[:div.code-row-lang [:div {:class (stl/css :code-row-lang)}
[:& select {:default-value markup-type [:button {:class (stl/css :toggle-btn)
:class "input-option" :data-type "markup"
:options [{:label "HTML" :value "html"} :on-click handle-collapse}
{:label "SVG" :value "svg"}] [:span {:class (stl/css-case
:on-change set-markup}] :collapsabled-icon true
:rotated collapsed-markup?)}
i/arrow-refactor]]
[:& select {:default-value markup-type
:class (stl/css :code-lang-select)
:options [{:label "HTML" :value "html"}
{:label "SVG" :value "svg"}]
:on-change set-markup}]
[:button.expand-button [:div {:class (stl/css :action-btns)}
{:on-click on-expand} [:button {:class (stl/css :expand-button)
i/full-screen] :on-click on-expand}
i/code-refactor]
[:& copy-button {:data #(replace-map markup-code images-data) [:& copy-button {:data #(replace-map markup-code images-data)
:on-copied on-markup-copied}]] :on-copied on-markup-copied}]]]
[:div.code-row-display {:style #js {"--code-height" (str (or markup-size 400) "px")}} (when-not collapsed-markup?
[:div {:class (stl/css :code-row-display)
:style #js {"--code-height" (str (or markup-size 400) "px")}}
[:& code-block {:type markup-type [:& code-block {:type markup-type
:code markup-code}]] :code markup-code}]])
[:div.resize-area {:on-pointer-down on-markup-pointer-down [:div {:class (stl/css :resize-area)
:on-lost-pointer-capture on-markup-lost-pointer-capture :on-pointer-down on-markup-pointer-down
:on-pointer-move on-markup-pointer-move}]]]))) :on-lost-pointer-capture on-markup-lost-pointer-capture
:on-pointer-move on-markup-pointer-move}]]]))

View File

@ -12,80 +12,85 @@
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
padding-bottom: $s-16; padding-bottom: $s-16;
}
.attributes-block { .download-button {
.download-button { @extend .button-secondary;
@extend .button-secondary; @include tabTitleTipography;
@include tabTitleTipography; height: $s-32;
height: $s-32; width: 100%;
width: 100%; margin: $s-8 0;
margin: $s-8 0; }
}
} .code-block {
.code-block { @include codeTypography;
@include codeTypography; display: flex;
display: flex; flex-direction: column;
flex-direction: column; flex: 1;
flex: 1; height: 100%;
min-height: 0;
overflow: hidden;
padding: 0 $s-4 $s-8 0;
pre {
border-radius: $br-8;
padding: $s-16;
max-height: var(--code-height);
overflow: auto;
height: 100%; height: 100%;
min-height: 0; }
overflow: hidden;
padding: 0 $s-4 $s-8 0;
pre { // Overrides background setted in the theme
border-radius: $br-8; :global(.hljs) {
padding: $s-16; background: $db-tertiary;
max-height: var(--code-height); }
overflow: auto; }
height: 100%;
}
// Overrides background setted in the theme .code-row-lang {
:global(.hljs) { display: flex;
background: $db-tertiary; justify-content: space-between;
} gap: $s-4;
} width: 100%;
.code-row-lang { }
display: flex;
justify-content: space-between; .code-lang {
gap: $s-4; @include tabTitleTipography;
width: 100%; display: flex;
} align-items: center;
.code-lang { }
@include tabTitleTipography;
display: flex; .action-btns {
align-items: center; display: flex;
} gap: $s-4;
.action-btns { flex: 1;
display: flex; justify-content: end;
gap: $s-4; }
flex: 1;
justify-content: end; .expand-button {
.expand-button { @extend .button-tertiary;
@extend .button-tertiary; height: $s-32;
height: $s-32; width: $s-28;
width: $s-28; svg {
svg { @extend .button-icon;
@extend .button-icon; stroke: var(--icon-foreground);
stroke: var(--icon-foreground);
}
}
}
.code-lang-select {
@include tabTitleTipography;
width: $s-72;
border: $s-1 solid transparent;
background-color: transparent;
color: var(--menu-foreground-color-disabled);
}
.code-row-display {
flex: 1;
min-height: 0;
overflow: hidden;
padding-bottom: $s-8;
} }
} }
.code-lang-select {
@include tabTitleTipography;
width: $s-72;
border: $s-1 solid transparent;
background-color: transparent;
color: var(--menu-foreground-color-disabled);
}
.code-row-display {
flex: 1;
min-height: 0;
overflow: hidden;
padding-bottom: $s-8;
}
.toggle-btn { .toggle-btn {
@include buttonStyle; @include buttonStyle;
display: flex; display: flex;

View File

@ -10,11 +10,8 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.types.component :as ctk] [app.common.types.component :as ctk]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.components.shape-icon :as si]
[app.main.ui.components.shape-icon-refactor :as sir] [app.main.ui.components.shape-icon-refactor :as sir]
[app.main.ui.components.tab-container :refer [tab-container tab-element]] [app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.viewer.inspect.attributes :refer [attributes]] [app.main.ui.viewer.inspect.attributes :refer [attributes]]
[app.main.ui.viewer.inspect.code :refer [code]] [app.main.ui.viewer.inspect.code :refer [code]]
@ -44,8 +41,7 @@
(mf/defc right-sidebar (mf/defc right-sidebar
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand] [{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
:or {from :inspect}}] :or {from :inspect}}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [section (mf/use-state :info #_:code)
section (mf/use-state :info #_:code)
objects (or objects (:objects page)) objects (or objects (:objects page))
shapes (or shapes shapes (or shapes
(resolve-shapes objects selected)) (resolve-shapes objects selected))
@ -86,113 +82,60 @@
(when-not (seq shapes) (when-not (seq shapes)
(handle-change-tab :info)))) (handle-change-tab :info))))
(if new-css-system [:aside {:class (stl/css-case :settings-bar-right true
[:aside {:class (stl/css-case :settings-bar-right true :viewer-code (= from :inspect))}
:viewer-code (= from :inspect))} (if (seq shapes)
(if (seq shapes) [:div {:class (stl/css :tool-windows)}
[:div {:class (stl/css :tool-windows)} [:div {:class (stl/css :shape-row)}
[:div {:class (stl/css :shape-row)} (if (> (count shapes) 1)
(if (> (count shapes) 1) [:*
[:* [:span {:class (stl/css :layers-icon)} i/layers-refactor]
[:span {:class (stl/css :layers-icon)} i/layers-refactor] [:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
[:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]] [:*
[:* [:span {:class (stl/css :shape-icon)}
[:span {:class (stl/css :shape-icon)} [:& sir/element-icon-refactor {:shape first-shape :main-instance? main-instance?}]]
[:& sir/element-icon-refactor {:shape first-shape :main-instance? main-instance?}]] ;; Execution time translation strings:
;; Execution time translation strings: ;; inspect.tabs.code.selected.circle
;; inspect.tabs.code.selected.circle ;; inspect.tabs.code.selected.component
;; inspect.tabs.code.selected.component ;; inspect.tabs.code.selected.curve
;; inspect.tabs.code.selected.curve ;; inspect.tabs.code.selected.frame
;; inspect.tabs.code.selected.frame ;; inspect.tabs.code.selected.group
;; inspect.tabs.code.selected.group ;; inspect.tabs.code.selected.image
;; inspect.tabs.code.selected.image ;; inspect.tabs.code.selected.mask
;; inspect.tabs.code.selected.mask ;; inspect.tabs.code.selected.path
;; inspect.tabs.code.selected.path ;; inspect.tabs.code.selected.rect
;; inspect.tabs.code.selected.rect ;; inspect.tabs.code.selected.svg-raw
;; inspect.tabs.code.selected.svg-raw ;; inspect.tabs.code.selected.text
;; inspect.tabs.code.selected.text [:span {:class (stl/css :layer-title)} (:name first-shape)]])]
[:span {:class (stl/css :layer-title)} (:name first-shape)]])] [:div {:class (stl/css :inspect-content)}
[:div {:class (stl/css :inspect-content)} [:& tab-container {:on-change-tab handle-change-tab
[:& tab-container {:on-change-tab handle-change-tab :selected @section}
:selected @section} [:& tab-element {:id :info :title (tr "inspect.tabs.info")}
[:& tab-element {:id :info :title (tr "inspect.tabs.info")} [:& attributes {:page-id page-id
[:& attributes {:page-id page-id :objects objects
:objects objects :file-id file-id
:file-id file-id :frame frame
:frame frame :shapes shapes
:shapes shapes :from from
:from from :libraries libraries
:libraries libraries :share-id share-id}]]
:share-id share-id}]]
[:& tab-element {:id :code :title (tr "inspect.tabs.code")} [:& tab-element {:id :code :title (tr "inspect.tabs.code")}
[:& code {:frame frame [:& code {:frame frame
:shapes shapes :shapes shapes
:on-expand handle-expand :on-expand handle-expand
:from from}]]]]] :from from}]]]]]
[:div {:class (stl/css :empty)} [:div {:class (stl/css :empty)}
[:div {:class (stl/css :code-info)} [:div {:class (stl/css :code-info)}
[:span {:class (stl/css :placeholder-icon)} [:span {:class (stl/css :placeholder-icon)}
i/code-refactor] i/code-refactor]
[:span {:class (stl/css :placeholder-label)} [:span {:class (stl/css :placeholder-label)}
(tr "inspect.empty.select")]] (tr "inspect.empty.select")]]
[:div {:class (stl/css :help-info)} [:div {:class (stl/css :help-info)}
[:span {:class (stl/css :placeholder-icon)} [:span {:class (stl/css :placeholder-icon)}
i/help-refactor] i/help-refactor]
[:span {:class (stl/css :placeholder-label)} [:span {:class (stl/css :placeholder-label)}
(tr "inspect.empty.help")]] (tr "inspect.empty.help")]]
[:button {:class (stl/css :more-info-btn) [:button {:class (stl/css :more-info-btn)
:on-click navigate-to-help} :on-click navigate-to-help}
(tr "inspect.empty.more-info")]])] (tr "inspect.empty.more-info")]])]))
[:aside.settings-bar.settings-bar-right
[:div.settings-bar-inside
(if (seq shapes)
[:div.tool-window
[:div.tool-window-bar.big
(if (> (count shapes) 1)
[:*
[:span.tool-window-bar-icon i/layers]
[:span.tool-window-bar-title (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
[:*
[:span.tool-window-bar-icon
[:& si/element-icon {:shape first-shape :main-instance? main-instance?}]]
;; Execution time translation strings:
;; inspect.tabs.code.selected.circle
;; inspect.tabs.code.selected.component
;; inspect.tabs.code.selected.curve
;; inspect.tabs.code.selected.frame
;; inspect.tabs.code.selected.group
;; inspect.tabs.code.selected.image
;; inspect.tabs.code.selected.mask
;; inspect.tabs.code.selected.path
;; inspect.tabs.code.selected.rect
;; inspect.tabs.code.selected.svg-raw
;; inspect.tabs.code.selected.text
[:span.tool-window-bar-title (:name first-shape)]])]
[:div.tool-window-content.inspect
[:& tabs-container {:on-change-tab handle-change-tab
:selected @section}
[:& tabs-element {:id :info :title (tr "inspect.tabs.info")}
[:& attributes {:page-id page-id
:objects objects
:file-id file-id
:frame frame
:shapes shapes
:from from
:libraries libraries
:share-id share-id}]]
[:& tabs-element {:id :code :title (tr "inspect.tabs.code")}
[:& code {:frame frame
:shapes shapes
:on-expand handle-expand
:from from}]]]]]
[:div.empty
[:span.tool-window-bar-icon i/code]
[:div (tr "inspect.empty.select")]
[:span.tool-window-bar-icon i/help]
[:div (tr "inspect.empty.help")]
[:button.btn-primary.action {:on-click navigate-to-help} (tr "inspect.empty.more-info")]])]])
))

View File

@ -16,63 +16,73 @@
grid-area: right-sidebar; grid-area: right-sidebar;
padding-top: $s-8; padding-top: $s-8;
padding-left: $s-12; padding-left: $s-12;
.tool-windows {
height: 100%;
display: flex;
flex-direction: column;
.shape-row {
display: flex;
gap: $s-8;
align-items: center;
margin-bottom: $s-16;
.layers-icon,
.shape-icon {
@include flexCenter;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
.layer-title {
@include titleTipography;
color: $df-primary;
}
}
}
.empty {
display: flex;
flex-direction: column;
align-items: center;
gap: $s-40;
padding-top: $s-24;
.code-info,
.help-info {
@include flexColumn;
align-items: center;
justify-content: flex-start;
gap: $s-8;
.placeholder-icon {
@extend .empty-icon;
}
.placeholder-label {
@include titleTipography;
text-align: center;
width: $s-200;
color: $df-secondary;
}
}
.more-info-btn {
@extend .button-secondary;
@include tabTitleTipography;
height: $s-32;
padding: $s-8 $s-24;
}
}
.inspect-content {
flex: 1;
overflow: hidden;
}
&.viewer-code { &.viewer-code {
height: calc(100vh - $s-48); height: calc(100vh - $s-48);
} }
} }
.tool-windows {
height: 100%;
display: flex;
flex-direction: column;
}
.shape-row {
display: flex;
gap: $s-8;
align-items: center;
margin-bottom: $s-16;
}
.layers-icon,
.shape-icon {
@include flexCenter;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
.layer-title {
@include titleTipography;
color: $df-primary;
}
.empty {
display: flex;
flex-direction: column;
align-items: center;
gap: $s-40;
padding-top: $s-24;
}
.code-info,
.help-info {
@include flexColumn;
align-items: center;
justify-content: flex-start;
gap: $s-8;
}
.placeholder-icon {
@extend .empty-icon;
}
.placeholder-label {
@include titleTipography;
text-align: center;
width: $s-200;
color: var(--empty-message-foreground-color);
}
.more-info-btn {
@extend .button-secondary;
@include tabTitleTipography;
height: $s-32;
padding: $s-8 $s-24;
}
.inspect-content {
flex: 1;
overflow: hidden;
}

View File

@ -14,7 +14,6 @@
[app.main.ui.auth.login :refer [login-methods]] [app.main.ui.auth.login :refer [login-methods]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]] [app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-methods register-validate-form register-success-page]] [app.main.ui.auth.register :refer [register-methods register-validate-form register-success-page]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :login-register} ::mf/register-as :login-register}
[_] [_]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [uri (. (. js/document -location) -href)
uri (. (. js/document -location) -href)
user-email (mf/use-state "") user-email (mf/use-state "")
register-token (mf/use-state "") register-token (mf/use-state "")
@ -71,114 +69,58 @@
(mf/with-effect [] (mf/with-effect []
(swap! storage assoc :redirect-url uri)) (swap! storage assoc :redirect-url uri))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")]
[:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :title (tr "labels.close")
:title (tr "labels.close") :on-click close} i/close-refactor]]
:on-click close} i/close-refactor]]
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(case current-section (case current-section
:login :login
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& login-methods {:on-success-callback success-login :origin :viewer}] [:& login-methods {:on-success-callback success-login :origin :viewer}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)} [:div {:class (stl/css :link-entry)}
[:a {:on-click set-section [:a {:on-click set-section
:data-value :recovery-request} :data-value :recovery-request}
(tr "auth.forgot-password")]] (tr "auth.forgot-password")]]
[:div {:class (stl/css :link-entry)} [:div {:class (stl/css :link-entry)}
[:span (tr "auth.register") " "] [:span (tr "auth.register") " "]
[:a {:on-click set-section [:a {:on-click set-section
:data-value :register} :data-value :register}
(tr "auth.register-submit")]]]] (tr "auth.register-submit")]]]]
:register :register
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register-methods {:on-success-callback success-register}] [:& register-methods {:on-success-callback success-register}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)} [:div {:class (stl/css :link-entry)}
[:span (tr "auth.already-have-account") " "] [:span (tr "auth.already-have-account") " "]
[:a {:on-click set-section [:a {:on-click set-section
:data-value :login} :data-value :login}
(tr "auth.login-here")]]]] (tr "auth.login-here")]]]]
:register-validate :register-validate
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register-validate-form {:params {:token @register-token} [:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:a {:on-click set-section
:data-value :register}
(tr "labels.go-back")]]]]
:recovery-request
[:& recovery-request-page {:go-back-callback go-back-to-login
:on-success-callback success-email-sent}] :on-success-callback success-email-sent}]
:email-sent [:div {:class (stl/css :links)}
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :link-entry)}
[:& register-success-page {:params {:email @user-email}}]]) [:a {:on-click set-section
:data-value :register}
(tr "labels.go-back")]]]]
(when main-section :recovery-request
[:div {:class (stl/css :links)} [:& recovery-request-page {:go-back-callback go-back-to-login
[:& terms-login]])]]] :on-success-callback success-email-sent}]
:email-sent
[:div {:class (stl/css :form-container)}
[:& register-success-page {:params {:email @user-email}}]])
(when main-section
;;OLD [:div {:class (stl/css :links)}
[:div.modal-overlay [:& terms-login]])]]]))
[:div.modal-container.login-register
[:div.title
[:div.modal-close-button {:on-click close :title (tr "labels.close")}
i/close]
(when main-section
[:h2 (tr "labels.continue-with-penpot")])]
[:div.modal-bottom.auth-content
(case current-section
:login
[:div.generic-form.login-form
[:div.form-container
[:& login-methods {:on-success-callback success-login}]
[:div.links
[:div.link-entry
[:a {:on-click #(set-current-section :recovery-request)}
(tr "auth.forgot-password")]]
[:div.link-entry
[:span (tr "auth.register") " "]
[:a {:on-click #(set-current-section :register)}
(tr "auth.register-submit")]]]]]
:register
[:div.form-container
[:& register-methods {:on-success-callback success-register}]
[:div.links
[:div.link-entry
[:span (tr "auth.already-have-account") " "]
[:a {:on-click #(set-current-section :login)}
(tr "auth.login-here")]]]]
:register-validate
[:div.form-container
[:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
[:div.links
[:div.link-entry
[:a {:on-click #(set-current-section :register)}
(tr "labels.go-back")]]]]
:recovery-request
[:& recovery-request-page {:go-back-callback #(set-current-section :login)
:on-success-callback success-email-sent}]
:email-sent
[:div.form-container
[:& register-success-page {:params {:email @user-email}}]])]
(when main-section
[:div.modal-footer.links
[:& terms-login]])]])))

View File

@ -18,7 +18,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -40,8 +39,7 @@
::mf/register-as :share-link ::mf/register-as :share-link
::mf/wrap-props false} ::mf/wrap-props false}
[{:keys [file page]}] [{:keys [file page]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [current-page page
current-page page
current-page-id (:id page) current-page-id (:id page)
slinks (mf/deref refs/share-links) slinks (mf/deref refs/share-links)
router (mf/deref refs/router) router (mf/deref refs/router)
@ -165,274 +163,151 @@
(reset! confirm* false) (reset! confirm* false)
(swap! options* assoc :who-comment value))] (swap! options* assoc :who-comment value))]
(if new-css-system [:div {:class (stl/css :share-modal)}
[:div {:class (stl/css :share-modal)} [:div {:class (stl/css :share-link-dialog)}
[:div {:class (stl/css :share-link-dialog)} [:div {:class (stl/css :share-link-header)}
[:div {:class (stl/css :share-link-header)} [:h2 {:class (stl/css :share-link-title)}
[:h2 {:class (stl/css :share-link-title)} (tr "common.share-link.title")]
(tr "common.share-link.title")] [:button {:class (stl/css :modal-close-button)
[:button {:class (stl/css :modal-close-button) :on-click on-close
:on-click on-close :title (tr "labels.close")}
:title (tr "labels.close")} i/close-refactor]]
i/close-refactor]] [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :share-link-section)}
[:div {:class (stl/css :share-link-section)} (when (and (not confirm?) (some? current-link))
(when (and (not confirm?) (some? current-link)) [:div {:class (stl/css :custon-input-wrapper)}
[:div {:class (stl/css :custon-input-wrapper)} [:input {:class (stl/css :input-text)
[:input {:class (stl/css :input-text) :type "text"
:type "text" :value (or current-link "")
:value (or current-link "") :placeholder (tr "common.share-link.placeholder")
:placeholder (tr "common.share-link.placeholder") :read-only true}]
:read-only true}]
[:button {:class (stl/css :copy-button)
:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/clipboard-refactor]])
[:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?)
[:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
(cond
(true? confirm?)
[:div {:class (stl/css :confirm-dialog)}
[:div {:class (stl/css :description)}
(tr "common.share-link.confirm-deletion-link-description")]
[:div {:class (stl/css :actions)}
[:input {:type "button"
:class (stl/css :button-cancel)
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input {:type "button"
:class (stl/css :button-danger)
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(some? current-link)
[:input
{:type "button"
:class (stl/css :button-danger)
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
:else
[:input
{:type "button"
:class (stl/css :button-active)
:on-click create-link
:value (tr "common.share-link.get-link")}])]]
[:button {:class (stl/css :copy-button)
:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/clipboard-refactor]])
[:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?) (when (not ^boolean confirm?)
[:div {:class (stl/css :permissions-section)} [:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
[:button {:class (stl/css :manage-permissions) (cond
:on-click toggle-perms-visibility} (true? confirm?)
[:span {:class (stl/css-case :icon true [:div {:class (stl/css :confirm-dialog)}
:rotated perms-visible?)} [:div {:class (stl/css :description)}
i/arrow-refactor] (tr "common.share-link.confirm-deletion-link-description")]
(tr "common.share-link.manage-ops")] [:div {:class (stl/css :actions)}
[:input {:type "button"
:class (stl/css :button-cancel)
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input {:type "button"
:class (stl/css :button-danger)
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(when ^boolean perms-visible? (some? current-link)
[:* [:input
(let [all-selected? (:all-pages options) {:type "button"
pages (->> (get-in file [:data :pages]) :class (stl/css :button-danger)
(map #(get-in file [:data :pages-index %]))) :on-click try-delete-link
selected (:pages options)] :value (tr "common.share-link.destroy-link")}]
[:div {:class (stl/css :view-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-pages")]
[:div {:class (stl/css :items)}
(if (= 1 (count pages))
[:div {:class (stl/css :checkbox-wrapper)} :else
[:input {:type "checkbox" [:input
:id (dm/str "page-" current-page-id) {:type "button"
:data-page-id (dm/str current-page-id) :class (stl/css :button-active)
:on-change on-mark-checked-page :on-click create-link
:checked true}] :value (tr "common.share-link.get-link")}])]]
[:label {:for (str "page-" current-page-id)} (:name current-page)]
[:span {:class (stl/css-case :checkobox-tick true
:global/checked true)}
i/status-tick-refactor]
[:span (str " " (tr "common.share-link.current-tag"))]]
[:*
[:div {:class (stl/css :select-all-row)}
[:div {:class (stl/css :checkbox-wrapper)}
[:label {:for "view-all"
:class (stl/css :select-all-label)}
[:span {:class (stl/css-case :global/checked all-selected?)}
(when all-selected?
i/status-tick-refactor)]
(tr "common.share-link.view-all")
[:input {:type "checkbox"
:id "view-all"
:checked all-selected?
:name "pages-mode"
:on-change on-toggle-all}]]]
[:span {:class (stl/css :count-pages)} (when (not ^boolean confirm?)
(tr "common.share-link.page-shared" (i18n/c (count selected)))]] [:div {:class (stl/css :permissions-section)}
[:button {:class (stl/css :manage-permissions)
:on-click toggle-perms-visibility}
[:span {:class (stl/css-case :icon true
:rotated perms-visible?)}
i/arrow-refactor]
(tr "common.share-link.manage-ops")]
[:ul {:class (stl/css :pages-selection)} (when ^boolean perms-visible?
(for [{:keys [id name]} pages] [:*
[:li {:class (stl/css :checkbox-wrapper) (let [all-selected? (:all-pages options)
:key (dm/str id)} pages (->> (get-in file [:data :pages])
[:label {:for (dm/str "page-" id)} (map #(get-in file [:data :pages-index %])))
[:span {:class (stl/css-case :global/checked (contains? selected id))} selected (:pages options)]
(when (contains? selected id) [:div {:class (stl/css :view-mode)}
i/status-tick-refactor)]
name
(when (= current-page-id id)
[:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
[:input {:type "checkbox"
:id (dm/str "page-" id)
:data-page-id (dm/str id)
:on-change on-mark-checked-page
:checked (contains? selected id)}]]])]])]])
[:div {:class (stl/css :access-mode)}
[:div {:class (stl/css :subtitle)} [:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-comment")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-comment-select)
:default-value (dm/str (:who-comment options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-comment-change}]]]
[:div {:class (stl/css :inspect-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-inspect")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-inspect-select)
:default-value (dm/str (:who-inspect options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-inspect-change}]]]])])]]]
;;OLD
[:div.modal-overlay.transparent.share-modal
[:div.modal-container.share-link-dialog
[:div.modal-content.initial
[:div.title
[:h2 (tr "common.share-link.title")]
[:div.modal-close-button
{:on-click on-close
:title (tr "labels.close")}
i/close]]]
[:div.modal-content
[:div.share-link-section
(when (and (not confirm?) (some? current-link))
[:div.custom-input.with-icon
[:input {:type "text"
:value (or current-link "")
:placeholder (tr "common.share-link.placeholder")
:read-only true}]
[:div.help-icon {:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/copy]])
[:div.hint-wrapper
(when (not ^boolean confirm?)
[:div.hint (tr "common.share-link.permissions-hint")])
(cond
(true? confirm?)
[:div.confirm-dialog
[:div.description (tr "common.share-link.confirm-deletion-link-description")]
[:div.actions
[:input.btn-secondary
{:type "button"
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input.btn-danger
{:type "button"
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(some? current-link)
[:input.btn-secondary
{:type "button"
:class "primary"
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
:else
[:input.btn-primary
{:type "button"
:class "primary"
:on-click create-link
:value (tr "common.share-link.get-link")}])]]]
[:div.modal-content.ops-section
[:div.manage-permissions
{:on-click toggle-perms-visibility}
[:span.icon i/picker-hsv]
[:div.title (tr "common.share-link.manage-ops")]]
(when ^boolean perms-visible?
[:*
(let [all-selected? (:all-pages options)
pages (->> (get-in file [:data :pages])
(map #(get-in file [:data :pages-index %])))
selected (:pages options)]
[:*
[:div.view-mode
[:div.subtitle
[:span.icon i/play]
(tr "common.share-link.permissions-pages")] (tr "common.share-link.permissions-pages")]
[:div.items [:div {:class (stl/css :items)}
(if (= 1 (count pages)) (if (= 1 (count pages))
[:div.input-checkbox.check-primary
[:div {:class (stl/css :checkbox-wrapper)}
[:input {:type "checkbox" [:input {:type "checkbox"
:id (dm/str "page-" current-page-id) :id (dm/str "page-" current-page-id)
:data-page-id (dm/str current-page-id) :data-page-id (dm/str current-page-id)
:on-change on-mark-checked-page :on-change on-mark-checked-page
:checked true}] :checked true}]
[:label {:for (str "page-" current-page-id)} (:name current-page)] [:label {:for (str "page-" current-page-id)} (:name current-page)]
[:span {:class (stl/css-case :checkobox-tick true
:global/checked true)}
i/status-tick-refactor]
[:span (str " " (tr "common.share-link.current-tag"))]] [:span (str " " (tr "common.share-link.current-tag"))]]
[:* [:*
[:div.row [:div {:class (stl/css :select-all-row)}
[:div.input-checkbox.check-primary [:div {:class (stl/css :checkbox-wrapper)}
[:input {:type "checkbox" [:label {:for "view-all"
:id "view-all" :class (stl/css :select-all-label)}
:checked all-selected? [:span {:class (stl/css-case :global/checked all-selected?)}
:name "pages-mode" (when all-selected?
:on-change on-toggle-all}] i/status-tick-refactor)]
[:label {:for "view-all"} (tr "common.share-link.view-all")]] (tr "common.share-link.view-all")
[:span.count-pages (tr "common.share-link.page-shared" (i18n/c (count selected)))]] [:input {:type "checkbox"
:id "view-all"
:checked all-selected?
:name "pages-mode"
:on-change on-toggle-all}]]]
[:ul.pages-selection [:span {:class (stl/css :count-pages)}
(tr "common.share-link.page-shared" (i18n/c (count selected)))]]
[:ul {:class (stl/css :pages-selection)}
(for [{:keys [id name]} pages] (for [{:keys [id name]} pages]
[:li.input-checkbox.check-primary {:key (dm/str id)} [:li {:class (stl/css :checkbox-wrapper)
[:input {:type "checkbox" :key (dm/str id)}
:id (dm/str "page-" id) [:label {:for (dm/str "page-" id)}
:data-page-id (dm/str id) [:span {:class (stl/css-case :global/checked (contains? selected id))}
:on-change on-mark-checked-page (when (contains? selected id)
:checked (contains? selected id)}] i/status-tick-refactor)]
(if (= current-page-id id) name
[:* (when (= current-page-id id)
[:label {:for (dm/str "page-" id)} name] [:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
[:span.current-tag (dm/str " " (tr "common.share-link.current-tag"))]] [:input {:type "checkbox"
[:label {:for (dm/str "page-" id)} name])])]])]]]) :id (dm/str "page-" id)
[:div.access-mode :data-page-id (dm/str id)
[:div.subtitle :on-change on-mark-checked-page
[:span.icon i/chat] :checked (contains? selected id)}]]])]])]])
(tr "common.share-link.permissions-can-comment")]
[:div.items [:div {:class (stl/css :access-mode)}
[:select.input-select {:on-change on-comment-change [:div {:class (stl/css :subtitle)}
:value (:who-comment options)} (tr "common.share-link.permissions-can-comment")]
[:option {:value "team"} (tr "common.share-link.team-members")] [:div {:class (stl/css :items)}
[:option {:value "all"} (tr "common.share-link.all-users")]]]] [:& select
[:div.inspect-mode {:class (stl/css :who-comment-select)
[:div.subtitle :default-value (dm/str (:who-comment options))
[:span.icon i/code] :options [{:value "team" :label (tr "common.share-link.team-members")}
(tr "common.share-link.permissions-can-inspect")] {:value "all" :label (tr "common.share-link.all-users")}]
[:div.items :on-change on-comment-change}]]]
[:select.input-select {:on-change on-inspect-change [:div {:class (stl/css :inspect-mode)}
:value (:who-inspect options)} [:div {:class (stl/css :subtitle)}
[:option {:value "team"} (tr "common.share-link.team-members")] (tr "common.share-link.permissions-can-inspect")]
[:option {:value "all"} (tr "common.share-link.all-users")]]]]])]]]))) [:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-inspect-select)
:default-value (dm/str (:who-inspect options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-inspect-change}]]]])])]]]))

View File

@ -48,6 +48,7 @@
} }
.hint { .hint {
flex-grow: 1; flex-grow: 1;
color: var(--modal-text-foreground-color);
} }
.custon-input-wrapper { .custon-input-wrapper {
@include flexRow; @include flexRow;
@ -68,6 +69,7 @@
border: $s-1 solid var(--input-border-color-active); border: $s-1 solid var(--input-border-color-active);
} }
} }
.copy-button { .copy-button {
@extend .button-secondary; @extend .button-secondary;
@include flexRow; @include flexRow;
@ -93,9 +95,11 @@
.button-active { .button-active {
@extend .modal-accept-btn; @extend .modal-accept-btn;
} }
.button-cancel { .button-cancel {
@extend .modal-cancel-btn; @extend .modal-cancel-btn;
} }
.button-danger { .button-danger {
@extend .modal-danger-btn; @extend .modal-danger-btn;
} }
@ -126,12 +130,20 @@
transform: rotate(90deg); transform: rotate(90deg);
} }
} }
.view-mode, .view-mode,
.access-mode, .access-mode,
.inspect-mode { .inspect-mode {
display: flex; display: flex;
width: 100%; width: 100%;
} }
.view-mode {
max-height: $s-248;
overflow: hidden auto;
scrollbar-gutter: stable;
}
.subtitle { .subtitle {
color: var(--modal-text-foreground-color); color: var(--modal-text-foreground-color);
display: flex; display: flex;

View File

@ -90,12 +90,12 @@
{:key (dm/str "workspace-" page-id) {:key (dm/str "workspace-" page-id)
:ref node-ref} :ref node-ref}
[:section.workspace-viewport [:section {:class (stl/css :workspace-viewport)}
(when (dbg/enabled? :coordinates) (when (dbg/enabled? :coordinates)
[:& coordinates/coordinates {:colorpalette? colorpalette?}]) [:& coordinates/coordinates {:colorpalette? colorpalette?}])
(when (dbg/enabled? :history-overlay) (when (dbg/enabled? :history-overlay)
[:div.history-debug-overlay [:div {:class (stl/css :history-debug-overlay)}
[:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"] [:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"]
[:& history-toolbox]]) [:& history-toolbox]])

View File

@ -40,3 +40,25 @@
} }
} }
} }
.workspace-content {
grid-area: viewport;
}
.history-debug-overlay {
bottom: 0;
max-height: $s-500;
width: $s-500;
overflow-y: auto;
position: absolute;
z-index: $z-index-modal;
}
.workspace-viewport {
overflow: hidden;
transition: none;
display: grid;
grid-template-rows: $s-20 1fr;
grid-template-columns: $s-20 1fr;
flex: 1;
}

View File

@ -10,7 +10,6 @@
[app.common.colors :as cc] [app.common.colors :as cc]
[app.common.data :as d] [app.common.data :as d]
[app.common.math :as mth] [app.common.math :as mth]
[app.main.ui.context :as ctx]
[app.util.dom :as dom] [app.util.dom :as dom]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -29,8 +28,7 @@
(* (/ val 255) 100)) (* (/ val 255) 100))
(mf/defc color-inputs [{:keys [type color disable-opacity on-change]}] (mf/defc color-inputs [{:keys [type color disable-opacity on-change]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [{red :r green :g blue :b
{red :r green :g blue :b
hue :h saturation :s value :v hue :h saturation :s value :v
hex :hex alpha :alpha} color hex :hex alpha :alpha} color
@ -115,133 +113,52 @@
property-val)] property-val)]
(dom/set-value! node new-val)))))))) (dom/set-value! node new-val))))))))
(if new-css-system [:div {:class (stl/css-case :color-values true
[:div {:class (stl/css-case :color-values true :disable-opacity disable-opacity)}
:disable-opacity disable-opacity)}
[:div {:class (stl/css :colors-row)} [:div {:class (stl/css :colors-row)}
(if (= type :rgb) (if (= type :rgb)
[:* [:*
[:div {:class (stl/css :input-wrapper)} [:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "R"] [:span {:class (stl/css :input-label)} "R"]
[:input {:id "red-value"
:ref (:r refs)
:type "number"
:min 0
:max 255
:default-value red
:on-change (on-change-property :r 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "G"]
[:input {:id "green-value"
:ref (:g refs)
:type "number"
:min 0
:max 255
:default-value green
:on-change (on-change-property :g 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "B"]
[:input {:id "blue-value"
:ref (:b refs)
:type "number"
:min 0
:max 255
:default-value blue
:on-change (on-change-property :b 255)}]]]
[:*
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "H"]
[:input {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:max 360
:default-value hue
:on-change (on-change-property :h 360)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "S"]
[:input {:id "saturation-value"
:ref (:s refs)
:type "number"
:min 0
:max 100
:step 1
:default-value saturation
:on-change (on-change-property :s 100)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "V"]
[:input {:id "value-value"
:ref (:v refs)
:type "number"
:min 0
:max 100
:default-value value
:on-change (on-change-property :v 100)}]]])]
[:div {:class (stl/css :hex-alpha-wrapper)}
[:div {:class (stl/css-case :input-wrapper true
:hex true)}
[:span {:class (stl/css :input-label)} "HEX"]
[:input {:id "hex-value"
:ref (:hex refs)
:default-value hex
:on-change on-change-hex
:on-blur on-blur-hex}]]
(when (not disable-opacity)
[:div {:class (stl/css-case :input-wrapper true)}
[:span {:class (stl/css :input-label)} "A"]
[:input {:id "alpha-value"
:ref (:alpha refs)
:type "number"
:min 0
:step 1
:max 100
:default-value (if (= alpha :multiple) "" alpha)
:on-change on-change-opacity}]])]]
[:div.color-values
{:class (when disable-opacity "disable-opacity")}
[:input {:id "hex-value"
:ref (:hex refs)
:default-value hex
:on-change on-change-hex
:on-blur on-blur-hex}]
(if (= type :rgb)
[:*
[:input {:id "red-value" [:input {:id "red-value"
:ref (:r refs) :ref (:r refs)
:type "number" :type "number"
:min 0 :min 0
:max 255 :max 255
:default-value red :default-value red
:on-change (on-change-property :r 255)}] :on-change (on-change-property :r 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "G"]
[:input {:id "green-value" [:input {:id "green-value"
:ref (:g refs) :ref (:g refs)
:type "number" :type "number"
:min 0 :min 0
:max 255 :max 255
:default-value green :default-value green
:on-change (on-change-property :g 255)}] :on-change (on-change-property :g 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "B"]
[:input {:id "blue-value" [:input {:id "blue-value"
:ref (:b refs) :ref (:b refs)
:type "number" :type "number"
:min 0 :min 0
:max 255 :max 255
:default-value blue :default-value blue
:on-change (on-change-property :b 255)}]] :on-change (on-change-property :b 255)}]]]
[:*
[:*
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "H"]
[:input {:id "hue-value" [:input {:id "hue-value"
:ref (:h refs) :ref (:h refs)
:type "number" :type "number"
:min 0 :min 0
:max 360 :max 360
:default-value hue :default-value hue
:on-change (on-change-property :h 360)}] :on-change (on-change-property :h 360)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "S"]
[:input {:id "saturation-value" [:input {:id "saturation-value"
:ref (:s refs) :ref (:s refs)
:type "number" :type "number"
@ -249,35 +166,33 @@
:max 100 :max 100
:step 1 :step 1
:default-value saturation :default-value saturation
:on-change (on-change-property :s 100)}] :on-change (on-change-property :s 100)}]]
[:div {:class (stl/css :input-wrapper)}
[:span {:class (stl/css :input-label)} "V"]
[:input {:id "value-value" [:input {:id "value-value"
:ref (:v refs) :ref (:v refs)
:type "number" :type "number"
:min 0 :min 0
:max 100 :max 100
:default-value value :default-value value
:on-change (on-change-property :v 100)}]]) :on-change (on-change-property :v 100)}]]])]
[:div {:class (stl/css :hex-alpha-wrapper)}
(when (not disable-opacity) [:div {:class (stl/css-case :input-wrapper true
[:input.alpha-value {:id "alpha-value" :hex true)}
:ref (:alpha refs) [:span {:class (stl/css :input-label)} "HEX"]
:type "number" [:input {:id "hex-value"
:min 0 :ref (:hex refs)
:step 1 :default-value hex
:max 100 :on-change on-change-hex
:default-value (if (= alpha :multiple) "" alpha) :on-blur on-blur-hex}]]
:on-change on-change-opacity}]) (when (not disable-opacity)
[:div {:class (stl/css-case :input-wrapper true)}
[:label.hex-label {:for "hex-value"} "HEX"] [:span {:class (stl/css :input-label)} "A"]
(if (= type :rgb) [:input {:id "alpha-value"
[:* :ref (:alpha refs)
[:label.red-label {:for "red-value"} "R"] :type "number"
[:label.green-label {:for "green-value"} "G"] :min 0
[:label.blue-label {:for "blue-value"} "B"]] :step 1
[:* :max 100
[:label.red-label {:for "hue-value"} "H"] :default-value (if (= alpha :multiple) "" alpha)
[:label.green-label {:for "saturation-value"} "S"] :on-change on-change-opacity}]])]]))
[:label.blue-label {:for "value-value"} "V"]])
(when (not disable-opacity)
[:label.alpha-label {:for "alpha-value"} "A"])])))

View File

@ -28,8 +28,7 @@
(mf/defc sidebar-options (mf/defc sidebar-options
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [{cmode :mode cshow :show} (mf/deref refs/comments-local)
{cmode :mode cshow :show} (mf/deref refs/comments-local)
update-mode update-mode
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
@ -45,53 +44,30 @@
(let [mode (if (= :pending cshow) :all :pending)] (let [mode (if (= :pending cshow) :all :pending)]
(st/emit! (dcm/update-filters {:show mode})))))] (st/emit! (dcm/update-filters {:show mode})))))]
(if new-css-system [:ul {:class (stl/css :comment-mode-dropdown)}
[:ul {:class (stl/css :comment-mode-dropdown)} [:li {:class (stl/css-case :dropdown-item true
[:li {:class (stl/css-case :dropdown-item true :selected (or (= :all cmode) (nil? cmode)))
:selected (or (= :all cmode) (nil? cmode))) :data-value "all"
:data-value "all" :on-click update-mode}
:on-click update-mode}
[:span {:class (stl/css :label)} (tr "labels.show-all-comments")] [:span {:class (stl/css :label)} (tr "labels.show-all-comments")]
[:span {:class (stl/css :icon)} i/tick-refactor]] [:span {:class (stl/css :icon)} i/tick-refactor]]
[:li {:class (stl/css-case :dropdown-item true [:li {:class (stl/css-case :dropdown-item true
:selected (= :yours cmode)) :selected (= :yours cmode))
:data-value "yours" :data-value "yours"
:on-click update-mode} :on-click update-mode}
[:span {:class (stl/css :label)} (tr "labels.show-your-comments")] [:span {:class (stl/css :label)} (tr "labels.show-your-comments")]
[:span {:class (stl/css :icon)} i/tick-refactor]] [:span {:class (stl/css :icon)} i/tick-refactor]]
[:li {:class (stl/css :separator)}] [:li {:class (stl/css :separator)}]
[:li {:class (stl/css-case :dropdown-item true [:li {:class (stl/css-case :dropdown-item true
:selected (= :pending cshow)) :selected (= :pending cshow))
:on-click update-show} :on-click update-show}
[:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")] [:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")]
[:span {:class (stl/css :icon)} i/tick-refactor]]] [:span {:class (stl/css :icon)} i/tick-refactor]]]))
[:ul.dropdown.with-check
[:li {:class (dom/classnames :selected (or (= :all cmode) (nil? cmode)))
:data-value "all"
:on-click update-mode}
[:span.icon i/tick]
[:span.label (tr "labels.show-all-comments")]]
[:li {:class (dom/classnames :selected (= :yours cmode))
:data-value "yours"
:on-click update-mode}
[:span.icon i/tick]
[:span.label (tr "labels.show-your-comments")]]
[:hr]
[:li {:class (dom/classnames :selected (= :pending cshow))
:on-click update-show}
[:span.icon i/tick]
[:span.label (tr "labels.hide-resolved-comments")]]])))
(mf/defc comments-sidebar (mf/defc comments-sidebar
[{:keys [users threads page-id from-viewer]}] [{:keys [users threads page-id from-viewer]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [threads-map (mf/deref refs/threads-ref)
threads-map (mf/deref refs/threads-ref)
profile (mf/deref refs/profile) profile (mf/deref refs/profile)
users-refs (mf/deref refs/current-file-comments-users) users-refs (mf/deref refs/current-file-comments-users)
users (or users users-refs) users (or users users-refs)
@ -139,75 +115,41 @@
(dwcm/center-to-comment-thread thread) (dwcm/center-to-comment-thread thread)
(-> (dcm/open-thread thread) (-> (dcm/open-thread thread)
(with-meta {::ev/origin "workspace"})))))))] (with-meta {::ev/origin "workspace"})))))))]
(if new-css-system [:div {:class (stl/css :comments-section)}
[:div {:class (stl/css :comments-section)} [:div {:class (stl/css :comments-section-title)}
[:div {:class (stl/css :comments-section-title)} [:span (tr "labels.comments")]
[:span (tr "labels.comments")] [:button {:class (stl/css :close-button)
[:button {:class (stl/css :close-button) :on-click close-section}
:on-click close-section} i/close-refactor]]
i/close-refactor]]
[:button {:class (stl/css :mode-dropdown-wrapper) [:button {:class (stl/css :mode-dropdown-wrapper)
:on-click toggle-mode-selector} :on-click toggle-mode-selector}
[:span {:class (stl/css :mode-label)} (case (:mode local) [:span {:class (stl/css :mode-label)} (case (:mode local)
(nil :all) (tr "labels.show-all-comments") (nil :all) (tr "labels.show-all-comments")
:yours (tr "labels.show-your-comments"))] :yours (tr "labels.show-your-comments"))]
[:div {:class (stl/css :icon)} i/arrow-refactor]] [:div {:class (stl/css :icon)} i/arrow-refactor]]
[:& dropdown {:show options? [:& dropdown {:show options?
:on-close #(reset! state* false)} :on-close #(reset! state* false)}
[:& sidebar-options {:local local}]] [:& sidebar-options {:local local}]]
[:div {:class (stl/css :comments-section-content)} [:div {:class (stl/css :comments-section-content)}
(if (seq tgroups) (if (seq tgroups)
[:div {:class (stl/css :thread-groups)} [:div {:class (stl/css :thread-groups)}
[:& cmt/comment-thread-group
{:group (first tgroups)
:on-thread-click on-thread-click
:users users}]
(for [tgroup (rest tgroups)]
[:& cmt/comment-thread-group [:& cmt/comment-thread-group
{:group (first tgroups) {:group tgroup
:on-thread-click on-thread-click :on-thread-click on-thread-click
:users users}] :users users
(for [tgroup (rest tgroups)] :key (:page-id tgroup)}])]
[:& cmt/comment-thread-group
{:group tgroup
:on-thread-click on-thread-click
:users users
:key (:page-id tgroup)}])]
[:div {:class (stl/css :thread-group-placeholder)} [:div {:class (stl/css :thread-group-placeholder)}
[:span {:class (stl/css :placeholder-icon)} i/comments-refactor] [:span {:class (stl/css :placeholder-icon)} i/comments-refactor]
[:span {:class (stl/css :placeholder-label)} [:span {:class (stl/css :placeholder-label)}
(tr "labels.no-comments-available")]])]] (tr "labels.no-comments-available")]])]]))
[:div.comments-section.comment-threads-section
[:div.workspace-comment-threads-sidebar-header
[:div.label (tr "labels.comments")]
[:div.options {:on-click toggle-mode-selector}
[:div.label (case (:mode local)
(nil :all) (tr "labels.all")
:yours (tr "labels.only-yours"))]
[:div.icon i/arrow-down]]
[:& dropdown {:show options?
:on-close #(reset! state* false)}
[:& sidebar-options {:local local}]]]
(if (seq tgroups)
[:div.thread-groups
[:& cmt/comment-thread-group
{:group (first tgroups)
:on-thread-click on-thread-click
:users users}]
(for [tgroup (rest tgroups)]
[:*
[:hr]
[:& cmt/comment-thread-group
{:group tgroup
:on-thread-click on-thread-click
:users users
:key (:page-id tgroup)}]])]
[:div.thread-groups-placeholder
i/chat
(tr "labels.no-comments-available")])])))

View File

@ -133,6 +133,7 @@
@include titleTipography; @include titleTipography;
text-align: center; text-align: center;
width: $s-184; width: $s-184;
color: var(--empty-message-foreground-color);
} }
} }
} }

View File

@ -19,7 +19,8 @@
height: $s-32; height: $s-32;
margin-right: $s-4; margin-right: $s-4;
svg { svg {
height: $s-32; min-height: $s-32;
width: $s-32;
fill: var(--icon-foreground-hover); fill: var(--icon-foreground-hover);
} }
} }

View File

@ -39,9 +39,11 @@
stroke: var(--icon-foreground); stroke: var(--icon-foreground);
} }
} }
.modal-title { .modal-title {
@include tabTitleTipography; @include tabTitleTipography;
margin-bottom: $s-16; margin-bottom: $s-16;
color: var(--modal-title-foreground-color);
} }
.modal-content { .modal-content {
@ -161,6 +163,7 @@
.section-list-empty { .section-list-empty {
@include titleTipography; @include titleTipography;
@include flexCenter; @include flexCenter;
color: var(--empty-message-foreground-color);
svg { svg {
@extend .button-icon-small; @extend .button-icon-small;

View File

@ -12,7 +12,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -32,8 +31,7 @@
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :nudge-option} ::mf/register-as :nudge-option}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [profile (mf/deref refs/profile)
profile (mf/deref refs/profile)
nudge (or (get-in profile [:props :nudge]) {:big 10 :small 1}) nudge (or (get-in profile [:props :nudge]) {:big 10 :small 1})
update-big (mf/use-fn #(st/emit! (dw/update-nudge {:big %}))) update-big (mf/use-fn #(st/emit! (dw/update-nudge {:big %})))
update-small (mf/use-fn #(st/emit! (dw/update-nudge {:small %}))) update-small (mf/use-fn #(st/emit! (dw/update-nudge {:small %})))
@ -43,45 +41,24 @@
(->> (events/listen js/document EventType.KEYDOWN on-keydown) (->> (events/listen js/document EventType.KEYDOWN on-keydown)
(partial events/unlistenByKey))) (partial events/unlistenByKey)))
(if new-css-system [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-container)} [:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)} [:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
[:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")] [:button {:class (stl/css :modal-close-btn)
[:button {:class (stl/css :modal-close-btn) :on-click on-close} i/close-refactor]]
:on-click on-close} i/close-refactor]] [:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :input-wrapper)}
[:div {:class (stl/css :input-wrapper)} [:label {:class (stl/css :modal-msg)
[:label {:class (stl/css :modal-msg) :for "nudge-small"} (tr "modals.small-nudge")]
:for "nudge-small"} (tr "modals.small-nudge")] [:> numeric-input* {:min 0.01
[:> numeric-input* {:min 0.01 :id "nudge-small"
:id "nudge-small" :value (:small nudge)
:value (:small nudge) :on-change update-small}]]
:on-change update-small}]] [:div {:class (stl/css :input-wrapper)}
[:div {:class (stl/css :input-wrapper)} [:label {:class (stl/css :modal-msg)
[:label {:class (stl/css :modal-msg) :for "nudge-big"} (tr "modals.big-nudge")]
:for "nudge-big"} (tr "modals.big-nudge")] [:> numeric-input* {:min 0.01
[:> numeric-input* {:min 0.01 :id "nudge-big"
:id "nudge-big" :value (:big nudge)
:value (:big nudge) :on-change update-big}]]]]]))
:on-change update-big}]]]]]
[:div.nudge-modal-overlay
[:div.nudge-modal-container
[:div.nudge-modal-header
[:p.nudge-modal-title (tr "modals.nudge-title")]
[:button.modal-close-button {:on-click on-close} i/close]]
[:div.nudge-modal-body
[:div.input-wrapper
[:span
[:p.nudge-subtitle (tr "modals.small-nudge")]
[:> numeric-input* {:min 0.01
:value (:small nudge)
:on-change update-small}]]]
[:div.input-wrapper
[:span
[:p.nudge-subtitle (tr "modals.big-nudge")]
[:> numeric-input* {:min 0.01
:value (:big nudge)
:on-change update-big}]]]]]])))

View File

@ -8,33 +8,37 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
.modal-container { }
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content { .modal-container {
@include flexColumn; @extend .modal-container-base;
gap: $s-24; min-width: $s-408;
@include titleTipography; border: $s-1 solid var(--modal-border-color);
margin-bottom: $s-24; }
.input-wrapper {
@extend .input-with-label; .modal-header {
label { margin-bottom: $s-24;
text-transform: none; }
}
} .modal-title {
} @include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include flexColumn;
gap: $s-24;
@include titleTipography;
margin-bottom: $s-24;
}
.input-wrapper {
@extend .input-with-label;
label {
text-transform: none;
} }
} }

View File

@ -12,10 +12,7 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.tab-container :refer [tab-container tab-element]] [app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks.resize :refer [use-resize-hook]] [app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.comments :refer [comments-sidebar]] [app.main.ui.workspace.comments :refer [comments-sidebar]]
[app.main.ui.workspace.left-header :refer [left-header]] [app.main.ui.workspace.left-header :refer [left-header]]
[app.main.ui.workspace.right-header :refer [right-header]] [app.main.ui.workspace.right-header :refer [right-header]]
@ -26,7 +23,6 @@
[app.main.ui.workspace.sidebar.options :refer [options-toolbox]] [app.main.ui.workspace.sidebar.options :refer [options-toolbox]]
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]] [app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]] [app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[app.util.object :as obj] [app.util.object :as obj]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -47,7 +43,6 @@
(contains? layout :assets) :assets) (contains? layout :assets) :assets)
shortcuts? (contains? layout :shortcuts) shortcuts? (contains? layout :shortcuts)
show-debug? (contains? layout :debug-panel) show-debug? (contains? layout :debug-panel)
new-css-system (mf/use-ctx ctx/new-css-system)
{on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size} {on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size}
(use-resize-hook :left-sidebar 275 275 500 :x false :left) (use-resize-hook :left-sidebar 275 275 500 :x false :left)
@ -65,25 +60,17 @@
[:aside {:ref parent-ref [:aside {:ref parent-ref
:id "left-sidebar-aside" :id "left-sidebar-aside"
:data-size size :data-size size
:class (stl/css-case new-css-system :class (stl/css-case :left-settings-bar true
:global/settings-bar (not new-css-system)
:global/settings-bar-left (not new-css-system)
:left-settings-bar true
:global/two-row (<= size 300) :global/two-row (<= size 300)
:global/three-row (and (> size 300) (<= size 400)) :global/three-row (and (> size 300) (<= size 400))
:global/four-row (> size 400)) :global/four-row (> size 400))
:style #js {"--width" (dm/str size "px")}} :style #js {"--width" (dm/str size "px")}}
(when new-css-system [:& left-header {:file file :layout layout :project project :page-id page-id}]
[:& left-header {:file file :layout layout :project project :page-id page-id}])
[:div {:on-pointer-down on-pointer-down [:div {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture :on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move :on-pointer-move on-pointer-move
:class (if ^boolean new-css-system :class (stl/css :resize-area)}]
(stl/css :resize-area) [:div {:class (stl/css :settings-bar-inside)}
(dom/classnames :resize-area true))}]
[:div {:class (if ^boolean new-css-system
(stl/css :settings-bar-inside)
(dom/classnames :settings-bar-inside true))}
(cond (cond
(true? shortcuts?) (true? shortcuts?)
[:& shortcuts-container] [:& shortcuts-container]
@ -92,64 +79,32 @@
[:& debug-panel] [:& debug-panel]
:else :else
(if ^boolean new-css-system [:div {:class (stl/css :tabs-wrapper)}
[:div {:class (stl/css :tabs-wrapper)} [:& tab-container
[:& tab-container {:on-change-tab on-tab-change
{:on-change-tab on-tab-change :selected section
:selected section :shortcuts? shortcuts?
:shortcuts? shortcuts? :collapsable? true
:collapsable? true :handle-collapse handle-collapse
:handle-collapse handle-collapse :class (stl/css :tab-spacing)}
:class (stl/css :tab-spacing)} [:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")} [:div {:class (stl/css :layers-tab)
[:div {:class (stl/css :layers-tab) :style #js {"--height" (str size-pages "px")}}
:style #js {"--height" (str size-pages "px")}} [:& sitemap {:layout layout
[:& sitemap {:layout layout :toggle-pages toggle-pages
:toggle-pages toggle-pages :show-pages? @show-pages?
:show-pages? @show-pages? :size size-pages}]
:size size-pages}] (when @show-pages?
(when @show-pages? [:div {:class (stl/css :resize-area-horiz)
[:div {:class (stl/css :resize-area-horiz) :on-pointer-down on-pointer-down-pages
:on-pointer-down on-pointer-down-pages :on-lost-pointer-capture on-lost-pointer-capture-pages
:on-lost-pointer-capture on-lost-pointer-capture-pages :on-pointer-move on-pointer-move-pages}])
:on-pointer-move on-pointer-move-pages}]) [:& layers-toolbox {:size-parent size
[:& layers-toolbox {:size-parent size :size size-pages}]]]
:size size-pages}]]]
(when-not ^boolean mode-inspect? (when-not ^boolean mode-inspect?
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")} [:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
[:& assets-toolbox]])]] [:& assets-toolbox]])]])]]))
[:*
[:button.collapse-sidebar
{:on-click handle-collapse
:aria-label (tr "workspace.sidebar.collapse")}
i/arrow-slide]
[:& tabs-container
{:on-change-tab on-tab-change
:selected section
:shortcuts? shortcuts?
:collapsable? true
:handle-collapse handle-collapse}
[:& tabs-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:div {:class :layers-tab
:style #js {"--height" (str size-pages "px")}}
[:& sitemap {:layout layout
:toggle-pages toggle-pages
:show-pages? @show-pages?
:size size-pages}]
(when @show-pages?
[:div.resize-area-horiz
{:on-pointer-down on-pointer-down-pages
:on-lost-pointer-capture on-lost-pointer-capture-pages
:on-pointer-move on-pointer-move-pages}])
[:& layers-toolbox {:size-parent size}]]]
(when-not ^boolean mode-inspect?
[:& tabs-element {:id :assets :title (tr "workspace.toolbar.assets")}
[:& assets-toolbox]])]]))]]))
;; --- Right Sidebar (Component) ;; --- Right Sidebar (Component)

View File

@ -64,8 +64,8 @@
(mf/html [:div {:class (stl/css :special-title)} (mf/html [:div {:class (stl/css :special-title)}
file-name]))} file-name]))}
(when-not local? (when-not local?
[:span.tool-link.tooltip.tooltip-left {:alt "Open library file"} [:span {:title "Open library file"}
[:a {:class (dom/classnames true) [:a {:class (stl/css :file-link)
:href (str "#" url) :href (str "#" url)
:target "_blank" :target "_blank"
:on-click dom/stop-propagation} :on-click dom/stop-propagation}

View File

@ -147,23 +147,6 @@
(t locale "workspace.undo.entry.unknown" value)))) (t locale "workspace.undo.entry.unknown" value))))
(defn entry->icon [{:keys [type]}] (defn entry->icon [{:keys [type]}]
(case type
:page i/file-html
:shape i/layers
:rect i/box
:circle i/circle
:text i/text
:path i/curve
:frame i/artboard
:group i/folder
:color i/palette
:typography i/titlecase
:component i/component
:media i/image
:image i/image
i/layers))
(defn entry->icon-refactor [{:keys [type]}]
(case type (case type
:page i/document-refactor :page i/document-refactor
:shape i/svg-refactor :shape i/svg-refactor
@ -310,9 +293,10 @@
:on-pointer-enter #(reset! hover? true) :on-pointer-enter #(reset! hover? true)
:on-pointer-leave #(reset! hover? false) :on-pointer-leave #(reset! hover? false)
:on-click #(st/emit! (dwc/undo-to-index idx-entry))} :on-click #(st/emit! (dwc/undo-to-index idx-entry))}
[:div {:class (stl/css :history-entry-summary)} [:div {:class (stl/css :history-entry-summary)}
[:div {:class (stl/css :history-entry-summary-icon)} [:div {:class (stl/css :history-entry-summary-icon)}
(entry->icon-refactor entry)] (entry->icon entry)]
[:div {:class (stl/css :history-entry-summary-text)} (entry->message locale entry)] [:div {:class (stl/css :history-entry-summary-text)} (entry->message locale entry)]
(when (:detail entry) (when (:detail entry)
[:div {:class (stl/css-case :history-entry-summary-button true [:div {:class (stl/css-case :history-entry-summary-button true

View File

@ -60,7 +60,7 @@
.history-entry-empty-msg { .history-entry-empty-msg {
@include titleTipography; @include titleTipography;
color: var(--title-foreground-secondary); color: var(--empty-message-foreground-color);
} }
.history-entries { .history-entries {
@ -115,7 +115,7 @@
.history-entry-detail { .history-entry-detail {
display: block; display: block;
padding-top: $s-16; padding-top: $s-16;
color: var(--modal-text-foreground-color);
.history-entry-details-list { .history-entry-details-list {
margin: 0; margin: 0;
} }

View File

@ -14,7 +14,6 @@
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -23,40 +22,24 @@
{::mf/wrap [mf/memo] {::mf/wrap [mf/memo]
::mf/wrap-props false} ::mf/wrap-props false}
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [options (mf/deref refs/workspace-page-options)
options (mf/deref refs/workspace-page-options)
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %))) on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options))) on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))] on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
(if new-css-system [:div {:class (stl/css :element-set)}
[:div {:class (stl/css :element-set)} [:div {:class (stl/css :element-title)}
[:div {:class (stl/css :element-title)} [:& title-bar {:collapsable? false
[:& title-bar {:collapsable? false :title (tr "workspace.options.canvas-background")
:title (tr "workspace.options.canvas-background") :class (stl/css :title-spacing-page)}]]
:class (stl/css :title-spacing-page)}]] [:div {:class (stl/css :element-content)}
[:div {:class (stl/css :element-content)} [:& color-row
[:& color-row {:disable-gradient true
{:disable-gradient true :disable-opacity true
:disable-opacity true :disable-image true
:disable-image true :title (tr "workspace.options.canvas-background")
:title (tr "workspace.options.canvas-background") :color {:color (get options :background clr/canvas)
:color {:color (get options :background clr/canvas) :opacity 1}
:opacity 1} :on-change on-change
:on-change on-change :on-open on-open
:on-open on-open :on-close on-close}]]]))
:on-close on-close}]]]
[:div.element-set
[:div.element-set-title (tr "workspace.options.canvas-background")]
[:div.element-set-content
[:& color-row
{:disable-gradient true
:disable-opacity true
:disable-image true
:title (tr "workspace.options.canvas-background")
:color {:color (get options :background clr/canvas)
:opacity 1}
:on-change on-change
:on-open on-open
:on-close on-close}]]])))

View File

@ -15,7 +15,6 @@
[app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.libraries :as dwl]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.color-bullet-new :as cbn] [app.main.ui.components.color-bullet-new :as cbn]
[app.main.ui.components.color-input :refer [color-input*]] [app.main.ui.components.color-input :refer [color-input*]]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
@ -43,10 +42,9 @@
(mf/defc color-row (mf/defc color-row
[{:keys [index color disable-gradient disable-opacity disable-image on-change [{:keys [index color disable-gradient disable-opacity disable-image on-change
on-reorder on-detach on-open on-close title on-remove on-reorder on-detach on-open on-close on-remove
disable-drag on-focus on-blur select-only select-on-focus]}] disable-drag on-focus on-blur select-only select-on-focus]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system) (let [current-file-id (mf/use-ctx ctx/current-file-id)
current-file-id (mf/use-ctx ctx/current-file-id)
file-colors (mf/deref refs/workspace-file-colors) file-colors (mf/deref refs/workspace-file-colors)
shared-libs (mf/deref refs/workspace-libraries) shared-libs (mf/deref refs/workspace-libraries)
hover-detach (mf/use-state false) hover-detach (mf/use-state false)
@ -186,152 +184,87 @@
(when (not= prev-color color) (when (not= prev-color color)
(modal/update-props! :colorpicker {:data (parse-color color)}))) (modal/update-props! :colorpicker {:data (parse-color color)})))
(if new-css-system [:div {:class (stl/css-case
[:div {:class (stl/css-case :color-data true
:color-data true :dnd-over-top (= (:over dprops) :top)
:dnd-over-top (= (:over dprops) :top) :dnd-over-bot (= (:over dprops) :bot))
:dnd-over-bot (= (:over dprops) :bot)) :ref dref}
:ref dref} [:span {:class (stl/css :color-info)}
[:span {:class (stl/css :color-info)} [:span {:class (stl/css-case :color-name-wrapper true
[:span {:class (stl/css-case :color-name-wrapper true :no-opacity (or disable-opacity
:no-opacity (or disable-opacity (not opacity?))
(not opacity?)) :library-name-wrapper library-color?
:library-name-wrapper library-color? :editing editing-text?
:editing editing-text? :gradient-name-wrapper gradient-color?)}
:gradient-name-wrapper gradient-color?)} [:span {:class (stl/css :color-bullet-wrapper)}
[:span {:class (stl/css :color-bullet-wrapper)} [:& cbn/color-bullet {:color (cond-> color
[:& cbn/color-bullet {:color (cond-> color (nil? color-name) (assoc
(nil? color-name) (assoc :id nil
:id nil :file-id nil))
:file-id nil)) :mini? true
:mini? true :on-click handle-click-color}]]
:on-click handle-click-color}]]
(cond
;; Rendering a color with ID
library-color?
[:*
[:div {:class (stl/css :color-name)
:title (str color-name)}
(str color-name)]
(when on-detach
[:button
{:class (stl/css :detach-btn)
:title (tr "settings.detach")
:on-pointer-enter #(reset! hover-detach true)
:on-pointer-leave #(reset! hover-detach false)
:on-click detach-value}
i/detach-refactor])]
;; Rendering a gradient
gradient-color?
[:*
[:div {:class (stl/css :color-name)}
(uc/gradient-type->string (get-in color [:gradient :type]))]]
;; Rendering an image
image-color?
[:*
[:div {:class (stl/css :color-name)}
(tr "media.image")]]
;; Rendering a plain color
:else
[:span {:class (stl/css :color-input-wrapper)}
[:> color-input* {:value (if multiple-colors?
""
(-> color :color cc/remove-hash))
:placeholder (tr "settings.multiple")
:className (stl/css :color-input)
:on-focus on-focus
:on-blur on-blur
:on-change handle-value-change}]])]
(when opacity?
[:div {:class (stl/css :opacity-element-wrapper)}
[:span {:class (stl/css :icon-text)}
"%"]
[:> numeric-input* {:value (-> color :opacity opacity->string)
:className (stl/css :opacity-input)
:placeholder "--"
:select-on-focus select-on-focus
:on-focus on-focus
:on-blur on-blur
:on-change handle-opacity-change
:min 0
:max 100}]])]
(when (some? on-remove)
[:button {:class (stl/css :remove-btn)
:on-click on-remove} i/remove-refactor])
(when select-only
[:button {:class (stl/css :select-btn)
:on-click handle-select}
i/move-refactor])]
;; OLD CSS
[:div.row-flex.color-data {:title title
:class (dom/classnames
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))
:ref dref}
[:& cb/color-bullet {:color (cond-> color
(nil? color-name) (assoc
:id nil
:file-id nil))
:on-click handle-click-color}]
(cond (cond
;; Rendering a color with ID ;; Rendering a color with ID
library-color? library-color?
[:* [:*
[:div.color-info [:div {:class (stl/css :color-name)
[:div.color-name (str color-name)]] :title (str color-name)}
(str color-name)]
(when on-detach (when on-detach
[:div.element-set-actions-button [:button
{:on-pointer-enter #(reset! hover-detach true) {:class (stl/css :detach-btn)
:title (tr "settings.detach")
:on-pointer-enter #(reset! hover-detach true)
:on-pointer-leave #(reset! hover-detach false) :on-pointer-leave #(reset! hover-detach false)
:on-click detach-value} :on-click detach-value}
(if @hover-detach i/unchain i/chain)])] i/detach-refactor])]
;; Rendering a gradient ;; Rendering a gradient
gradient-color? gradient-color?
[:* [:*
[:div.color-info [:div {:class (stl/css :color-name)}
[:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]] (uc/gradient-type->string (get-in color [:gradient :type]))]]
(when select-only
[:div.element-set-actions-button {:on-click handle-select}
i/pointer-inner])]
;; Rendering a plain color/opacity ;; Rendering an image
:else image-color?
[:* [:*
[:div.color-info [:div {:class (stl/css :color-name)}
[:> color-input* {:value (if multiple-colors? (tr "media.image")]]
""
(-> color :color cc/remove-hash)) ;; Rendering a plain color
:placeholder (tr "settings.multiple") :else
[:span {:class (stl/css :color-input-wrapper)}
[:> color-input* {:value (if multiple-colors?
""
(-> color :color cc/remove-hash))
:placeholder (tr "settings.multiple")
:className (stl/css :color-input)
:on-focus on-focus
:on-blur on-blur
:on-change handle-value-change}]])]
(when opacity?
[:div {:class (stl/css :opacity-element-wrapper)}
[:span {:class (stl/css :icon-text)}
"%"]
[:> numeric-input* {:value (-> color :opacity opacity->string)
:className (stl/css :opacity-input)
:placeholder "--"
:select-on-focus select-on-focus
:on-focus on-focus :on-focus on-focus
:on-blur on-blur :on-blur on-blur
:on-change handle-value-change}]] :on-change handle-opacity-change
:min 0
:max 100}]])]
(when (and (not disable-opacity) (when (some? on-remove)
(not (:gradient color))) [:button {:class (stl/css :remove-btn)
[:div.input-element :on-click on-remove} i/remove-refactor])
{:class (dom/classnames :percentail (not= (:opacity color) :multiple))} (when select-only
[:> numeric-input* {:value (-> color :opacity opacity->string) [:button {:class (stl/css :select-btn)
:placeholder (tr "settings.multiple") :on-click handle-select}
:select-on-focus select-on-focus i/move-refactor])]
:on-focus on-focus
:on-blur on-blur
:on-change handle-opacity-change
:min 0
:max 100}]])
(when select-only
[:div.element-set-actions-button {:on-click handle-select}
i/pointer-inner])])
(when (some? on-remove)
[:div.element-set-actions-button.remove {:on-click on-remove} i/minus])])
)) ))

View File

@ -8,155 +8,6 @@
.color-data { .color-data {
@include flexRow; @include flexRow;
.color-info {
display: flex;
align-items: center;
gap: $s-2;
border-radius: $s-8;
background-color: var(--input-details-color);
height: $s-32;
width: 100%;
flex-grow: 1;
.color-name-wrapper {
@extend .input-element;
flex-grow: 1;
width: 100%;
border-radius: $br-8 0 0 $br-8;
padding: 0;
margin-right: 0;
gap: $s-4;
input {
padding: 0;
}
.color-bullet-wrapper {
height: $s-28;
padding: 0 $s-2 0 $s-8;
border-radius: $br-8 0 0 $br-8;
background-color: transparent;
&:hover {
background-color: transparent;
}
}
.color-name {
@include titleTipography;
display: flex;
align-items: center;
height: $s-28;
padding-left: $s-6;
border-radius: $br-8;
width: 100%;
flex-grow: 1;
color: var(--input-foreground-color-active);
}
.detach-btn {
@extend .button-tertiary;
height: $s-28;
width: $s-28;
border-radius: 0 $br-8 $br-8 0;
display: none;
svg {
@extend .button-icon;
}
}
.color-input-wrapper {
@include titleTipography;
display: flex;
align-items: center;
height: $s-28;
padding: 0 $s-0;
width: 100%;
margin: 0;
flex-grow: 1;
background-color: var(--input-background-color);
color: var(--input-foreground-color);
border-radius: $br-0;
}
&.no-opacity {
border-radius: $br-8;
.color-input-wrapper {
border-radius: $br-8;
}
}
&:hover {
background-color: var(--input-background-color-hover);
border: $s-1 solid var(--input-background-color-hover);
.color-bullet-wrapper,
.color-name,
.detach-btn,
.color-input-wrapper {
background-color: var(--input-background-color-hover);
}
.detach-btn {
display: flex;
svg {
stroke: var(--input-foreground-color-active);
}
}
&.editing {
background-color: var(--input-background-color-active);
.color-bullet-wrapper,
.color-name,
.detach-btn,
.color-input-wrapper {
background-color: var(--input-background-color-active);
}
}
}
&:focus,
&:focus-within {
background-color: var(--input-background-color-active);
}
&.editing {
background-color: var(--input-background-color-active);
}
}
.gradient-name-wrapper {
border-radius: 0 $br-8 $br-8 0;
.color-name {
@include flexRow;
border-radius: 0 $br-8 $br-8 0;
}
}
.library-name-wrapper {
border-radius: $br-8;
}
.opacity-element-wrapper {
@extend .input-element;
width: $s-60;
border-radius: 0 $br-8 $br-8 0;
.opacity-input {
padding: 0;
border-radius: 0 $br-8 $br-8 0;
min-width: $s-28;
}
.icon-text {
@include flexCenter;
height: $s-32;
margin-right: $s-4;
padding-top: $s-2;
}
}
&:hover {
.detach-btn,
.select-btn {
background-color: transparent;
svg {
stroke: var(--input-foreground-color-active);
}
}
}
}
.remove-btn,
.select-btn {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
svg {
@extend .button-icon;
}
}
&.dnd-over-top { &.dnd-over-top {
border-top: $s-1 solid var(--layer-row-foreground-color-drag); border-top: $s-1 solid var(--layer-row-foreground-color-drag);
@ -165,3 +16,155 @@
border-bottom: $s-1 solid var(--layer-row-foreground-color-drag); border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
} }
} }
.color-info {
display: flex;
align-items: center;
gap: $s-2;
border-radius: $s-8;
background-color: var(--input-details-color);
height: $s-32;
width: 100%;
flex-grow: 1;
.color-name-wrapper {
@extend .input-element;
flex-grow: 1;
width: 100%;
border-radius: $br-8 0 0 $br-8;
padding: 0;
margin-right: 0;
gap: $s-4;
input {
padding: 0;
}
.color-bullet-wrapper {
height: $s-28;
padding: 0 $s-2 0 $s-8;
border-radius: $br-8 0 0 $br-8;
background-color: transparent;
&:hover {
background-color: transparent;
}
}
.color-name {
@include titleTipography;
display: flex;
align-items: center;
height: $s-28;
padding-left: $s-6;
border-radius: $br-8;
width: 100%;
flex-grow: 1;
color: var(--input-foreground-color-active);
}
.detach-btn {
@extend .button-tertiary;
height: $s-28;
width: $s-28;
border-radius: 0 $br-8 $br-8 0;
display: none;
svg {
@extend .button-icon;
}
}
.color-input-wrapper {
@include titleTipography;
display: flex;
align-items: center;
height: $s-28;
padding: 0 $s-0;
width: 100%;
margin: 0;
flex-grow: 1;
background-color: var(--input-background-color);
color: var(--input-foreground-color);
border-radius: $br-0;
}
&.no-opacity {
border-radius: $br-8;
.color-input-wrapper {
border-radius: $br-8;
}
}
&:hover {
background-color: var(--input-background-color-hover);
border: $s-1 solid var(--input-background-color-hover);
.color-bullet-wrapper,
.color-name,
.detach-btn,
.color-input-wrapper {
background-color: var(--input-background-color-hover);
}
.detach-btn {
display: flex;
svg {
stroke: var(--input-foreground-color-active);
}
}
&.editing {
background-color: var(--input-background-color-active);
.color-bullet-wrapper,
.color-name,
.detach-btn,
.color-input-wrapper {
background-color: var(--input-background-color-active);
}
}
}
&:focus,
&:focus-within {
background-color: var(--input-background-color-active);
}
&.editing {
background-color: var(--input-background-color-active);
}
}
.gradient-name-wrapper {
border-radius: 0 $br-8 $br-8 0;
.color-name {
@include flexRow;
border-radius: 0 $br-8 $br-8 0;
}
}
.library-name-wrapper {
border-radius: $br-8;
}
.opacity-element-wrapper {
@extend .input-element;
width: $s-60;
border-radius: 0 $br-8 $br-8 0;
.opacity-input {
padding: 0;
border-radius: 0 $br-8 $br-8 0;
min-width: $s-28;
}
.icon-text {
@include flexCenter;
height: $s-32;
margin-right: $s-4;
padding-top: $s-2;
}
}
&:hover {
.detach-btn,
.select-btn {
background-color: transparent;
svg {
stroke: var(--input-foreground-color-active);
}
}
}
}
.remove-btn,
.select-btn {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
svg {
@extend .button-icon;
}
}

Some files were not shown because too many files have changed in this diff Show More