Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-06-11 11:27:16 +02:00
commit c0919aff51
110 changed files with 1849 additions and 1757 deletions

View file

@ -20,15 +20,17 @@
### :sparkles: New features ### :sparkles: New features
- Fix clickable area of Penptot logo in the viewer [Taiga #7988](https://tree.taiga.io/project/penpot/issue/7988)
- Fix constraints dropdown when selecting multiple shapes [Taiga #7686](https://tree.taiga.io/project/penpot/issue/7686)
- Improve auth process [Taiga #7094](https://tree.taiga.io/project/penpot/us/7094) - Improve auth process [Taiga #7094](https://tree.taiga.io/project/penpot/us/7094)
- Add locking degrees increment (hold shift) on path edition [Taiga #7761](https://tree.taiga.io/project/penpot/issue/7761) - Add locking degrees increment (hold shift) on path edition [Taiga #7761](https://tree.taiga.io/project/penpot/issue/7761)
- Persistence & Concurrent Edition Enhancements [Taiga #5657](https://tree.taiga.io/project/penpot/us/5657) - Persistence & Concurrent Edition Enhancements [Taiga #5657](https://tree.taiga.io/project/penpot/us/5657)
- Allow library colors as recent colors [Taiga #7640](https://tree.taiga.io/project/penpot/issue/7640) - Allow library colors as recent colors [Taiga #7640](https://tree.taiga.io/project/penpot/issue/7640)
- Missing scroll in viewmode comments [Taiga #7427](https://tree.taiga.io/project/penpot/issue/7427)
- Comments in View mode should mimic the positioning behavior of the Workspace [Taiga #7346](https://tree.taiga.io/project/penpot/issue/7346)
### :bug: Bugs fixed ### :bug: Bugs fixed
- Fix clickable area of Penptot logo in the viewer [Taiga #7988](https://tree.taiga.io/project/penpot/issue/7988)
- Fix constraints dropdown when selecting multiple shapes [Taiga #7686](https://tree.taiga.io/project/penpot/issue/7686)
- Layout and scrollign fixes for the bottom palette [Taiga #7559](https://tree.taiga.io/project/penpot/issue/7559) - Layout and scrollign fixes for the bottom palette [Taiga #7559](https://tree.taiga.io/project/penpot/issue/7559)
- Fix expand libraries when search results are present [Taiga #7876](https://tree.taiga.io/project/penpot/issue/7876) - Fix expand libraries when search results are present [Taiga #7876](https://tree.taiga.io/project/penpot/issue/7876)
- Fix color palette default library [Taiga #8029](https://tree.taiga.io/project/penpot/issue/8029) - Fix color palette default library [Taiga #8029](https://tree.taiga.io/project/penpot/issue/8029)
@ -39,6 +41,9 @@
- Fix "Share prototypes" modal remains open [Taiga #7442](https://tree.taiga.io/project/penpot/issue/7442) - Fix "Share prototypes" modal remains open [Taiga #7442](https://tree.taiga.io/project/penpot/issue/7442)
- Fix "Components visibility and opacity" [#4694](https://github.com/penpot/penpot/issues/4694) - Fix "Components visibility and opacity" [#4694](https://github.com/penpot/penpot/issues/4694)
- Fix "Attribute overrides in copies are not exported in zip file" [Taiga #8072](https://tree.taiga.io/project/penpot/issue/8072) - Fix "Attribute overrides in copies are not exported in zip file" [Taiga #8072](https://tree.taiga.io/project/penpot/issue/8072)
- Fix group not automatically selected in the Layers panel after creation [Taiga #8078](https://tree.taiga.io/project/penpot/issue/8078)
- Fix export boards loses opacity [Taiga #7592](https://tree.taiga.io/project/penpot/issue/7592)
- Fix show in view mode and interactions workflow [Taiga #4711](https://github.com/penpot/penpot/pull/4711)
## 2.0.3 ## 2.0.3

View file

@ -6,4 +6,4 @@
(ns app.common.files.defaults) (ns app.common.files.defaults)
(def version 48) (def version 49)

View file

@ -937,6 +937,26 @@
(-> data (-> data
(update :pages-index update-vals update-page)))) (update :pages-index update-vals update-page))))
(defn migrate-up-49
"Remove hide-in-viewer for shapes that are origin or destination of an interaction"
[data]
(letfn [(update-object [destinations object]
(cond-> object
(or (:interactions object)
(contains? destinations (:id object)))
(dissoc object :hide-in-viewer)))
(update-page [page]
(let [destinations (->> page
:objects
(vals)
(mapcat :interactions)
(map :destination)
(set))]
(update page :objects update-vals (partial update-object destinations))))]
(update data :pages-index update-vals update-page)))
(def migrations (def migrations
"A vector of all applicable migrations" "A vector of all applicable migrations"
[{:id 2 :migrate-up migrate-up-2} [{:id 2 :migrate-up migrate-up-2}
@ -976,4 +996,5 @@
{:id 45 :migrate-up migrate-up-45} {:id 45 :migrate-up migrate-up-45}
{:id 46 :migrate-up migrate-up-46} {:id 46 :migrate-up migrate-up-46}
{:id 47 :migrate-up migrate-up-47} {:id 47 :migrate-up migrate-up-47}
{:id 48 :migrate-up migrate-up-48}]) {:id 48 :migrate-up migrate-up-48}
{:id 49 :migrate-up migrate-up-49}])

View file

@ -517,3 +517,16 @@
{:with-objects? true}) {:with-objects? true})
(pcb/reorder-grid-children [frame-id]))) (pcb/reorder-grid-children [frame-id])))
(pcb/remove-objects empty-parents)))) (pcb/remove-objects empty-parents))))
(defn change-show-in-viewer [shape hide?]
(cond-> (assoc shape :hide-in-viewer hide?)
;; When a frame is no longer shown in view mode, it cannot have interactions
hide?
(dissoc :interactions)))
(defn add-new-interaction [shape interaction]
(-> shape
(update :interactions ctsi/add-interaction interaction)
;; When a interaction is created, the frame must be shown in view mode
(dissoc :hide-in-viewer)))

View file

@ -16,6 +16,7 @@
[app.common.types.pages-list :as ctpl] [app.common.types.pages-list :as ctpl]
[app.common.types.shape :as cts] [app.common.types.shape :as cts]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.types.shape.interactions :as ctsi]
[app.common.types.typographies-list :as cttl] [app.common.types.typographies-list :as cttl]
[app.common.types.typography :as ctt])) [app.common.types.typography :as ctt]))
@ -99,3 +100,19 @@
[file label & {:keys [] :as params}] [file label & {:keys [] :as params}]
(let [typography (sample-typography label params)] (let [typography (sample-typography label params)]
(ctf/update-file-data file #(cttl/add-typography % typography)))) (ctf/update-file-data file #(cttl/add-typography % typography))))
(defn add-interaction
[file origin-label dest-label]
(let [page (thf/current-page file)
origin (get-shape file origin-label)
dest (get-shape file dest-label)
interaction (-> ctsi/default-interaction
(ctsi/set-destination (:id dest))
(assoc :position-relative-to (:id origin)))
interactions (ctsi/add-interaction (:interactions origin) interaction)]
(ctf/update-file-data
file
(fn [file-data]
(ctpl/update-page file-data
(:id page)
#(ctst/set-shape % (assoc origin :interactions interactions)))))))

View file

@ -0,0 +1,75 @@
;; 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
(ns common-tests.logic.hide-in-viewer-test
(:require
[app.common.files.changes-builder :as pcb]
[app.common.logic.shapes :as cls]
[app.common.test-helpers.compositions :as tho]
[app.common.test-helpers.files :as thf]
[app.common.test-helpers.ids-map :as thi]
[app.common.test-helpers.shapes :as ths]
[app.common.types.shape.interactions :as ctsi]
[clojure.test :as t]))
(t/use-fixtures :each thi/test-fixture)
(t/deftest test-remove-show-in-view-mode-delete-interactions
(let [;; ==== Setup
file (-> (thf/sample-file :file1)
(tho/add-frame :frame-dest)
(tho/add-frame :frame-origin)
(ths/add-interaction :frame-origin :frame-dest))
frame-origin (ths/get-shape file :frame-origin)
page (thf/current-page file)
;; ==== Action
changes (-> (pcb/empty-changes nil (:id page))
(pcb/with-objects (:objects page))
(pcb/update-shapes [(:id frame-origin)] #(cls/change-show-in-viewer % true)))
file' (thf/apply-changes file changes)
;; ==== Get
frame-origin' (ths/get-shape file' :frame-origin)]
;; ==== Check
(t/is (some? (:interactions frame-origin)))
(t/is (nil? (:interactions frame-origin')))))
(t/deftest test-add-new-interaction-updates-show-in-view-mode
(let [;; ==== Setup
file (-> (thf/sample-file :file1)
(tho/add-frame :frame-dest :hide-in-viewer true)
(tho/add-frame :frame-origin :hide-in-viewer true))
frame-dest (ths/get-shape file :frame-dest)
frame-origin (ths/get-shape file :frame-origin)
page (thf/current-page file)
;; ==== Action
new-interaction (-> ctsi/default-interaction
(ctsi/set-destination (:id frame-dest))
(assoc :position-relative-to (:id frame-dest)))
changes (-> (pcb/empty-changes nil (:id page))
(pcb/with-objects (:objects page))
(pcb/update-shapes [(:id frame-origin)] #(cls/add-new-interaction % new-interaction)))
file' (thf/apply-changes file changes)
;; ==== Get
frame-origin' (ths/get-shape file' :frame-origin)]
;; ==== Check
(t/is (true? (:hide-in-viewer frame-origin)))
(t/is (nil? (:hide-in-viewer frame-origin')))))

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,222 @@
{
"~:features":{
"~#set":[
"layout/grid",
"styles/v2",
"fdata/shape-data-type"
]
},
"~:permissions":{
"~:type":"~:membership",
"~:is-owner":true,
"~:is-admin":true,
"~:can-edit":true,
"~:can-read":true,
"~:is-logged":true
},
"~:has-media-trimmed":false,
"~:comment-thread-seqn":0,
"~:name":"New File 14",
"~:revn":1,
"~:modified-at":"~m1718088151182",
"~:id":"~u6191cd35-bb1f-81f7-8004-7cc63d087374",
"~:is-shared":false,
"~:version":48,
"~:project-id":"~u4dc640b0-5cbf-11ec-a7c5-91e9eb4f238d",
"~:created-at":"~m1718088142886",
"~:data":{
"~:pages":[
"~u6191cd35-bb1f-81f7-8004-7cc63d087375"
],
"~:pages-index":{
"~u6191cd35-bb1f-81f7-8004-7cc63d087375":{
"~:options":{
},
"~:objects":{
"~u00000000-0000-0000-0000-000000000000":{
"~#shape":{
"~:y":0,
"~:hide-fill-on-export":false,
"~:transform":{
"~#matrix":{
"~:a":1.0,
"~:b":0.0,
"~:c":0.0,
"~:d":1.0,
"~:e":0.0,
"~:f":0.0
}
},
"~:rotation":0,
"~:name":"Root Frame",
"~:width":0.01,
"~:type":"~:frame",
"~:points":[
{
"~#point":{
"~:x":0,
"~:y":0
}
},
{
"~#point":{
"~:x":0.01,
"~:y":0
}
},
{
"~#point":{
"~:x":0.01,
"~:y":0.01
}
},
{
"~#point":{
"~:x":0,
"~:y":0.01
}
}
],
"~:proportion-lock":false,
"~:transform-inverse":{
"~#matrix":{
"~:a":1.0,
"~:b":0.0,
"~:c":0.0,
"~:d":1.0,
"~:e":0.0,
"~:f":0.0
}
},
"~:id":"~u00000000-0000-0000-0000-000000000000",
"~:parent-id":"~u00000000-0000-0000-0000-000000000000",
"~:frame-id":"~u00000000-0000-0000-0000-000000000000",
"~:strokes":[
],
"~:x":0,
"~:proportion":1.0,
"~:selrect":{
"~#rect":{
"~:x":0,
"~:y":0,
"~:width":0.01,
"~:height":0.01,
"~:x1":0,
"~:y1":0,
"~:x2":0.01,
"~:y2":0.01
}
},
"~:fills":[
{
"~:fill-color":"#FFFFFF",
"~:fill-opacity":1
}
],
"~:flip-x":null,
"~:height":0.01,
"~:flip-y":null,
"~:shapes":[
"~u7c75e310-c3a2-80fd-8004-7cc641479aef"
]
}
},
"~u7c75e310-c3a2-80fd-8004-7cc641479aef":{
"~#shape":{
"~:y":436,
"~:rx":0,
"~:transform":{
"~#matrix":{
"~:a":1.0,
"~:b":0.0,
"~:c":0.0,
"~:d":1.0,
"~:e":0.0,
"~:f":0.0
}
},
"~:rotation":0,
"~:grow-type":"~:fixed",
"~:hide-in-viewer":false,
"~:name":"Rectangle",
"~:width":126.00000000000006,
"~:type":"~:rect",
"~:points":[
{
"~#point":{
"~:x":266,
"~:y":436
}
},
{
"~#point":{
"~:x":392.00000000000006,
"~:y":436
}
},
{
"~#point":{
"~:x":392.00000000000006,
"~:y":570
}
},
{
"~#point":{
"~:x":266,
"~:y":570
}
}
],
"~:proportion-lock":false,
"~:transform-inverse":{
"~#matrix":{
"~:a":1.0,
"~:b":0.0,
"~:c":0.0,
"~:d":1.0,
"~:e":0.0,
"~:f":0.0
}
},
"~:id":"~u7c75e310-c3a2-80fd-8004-7cc641479aef",
"~:parent-id":"~u00000000-0000-0000-0000-000000000000",
"~:frame-id":"~u00000000-0000-0000-0000-000000000000",
"~:strokes":[
],
"~:x":266,
"~:proportion":1,
"~:selrect":{
"~#rect":{
"~:x":266,
"~:y":436,
"~:width":126.00000000000006,
"~:height":134,
"~:x1":266,
"~:y1":436,
"~:x2":392.00000000000006,
"~:y2":570
}
},
"~:fills":[
{
"~:fill-color":"#B1B2B5",
"~:fill-opacity":1
}
],
"~:flip-x":null,
"~:ry":0,
"~:height":134,
"~:flip-y":null
}
}
},
"~:id":"~u6191cd35-bb1f-81f7-8004-7cc63d087375",
"~:name":"Page 1"
}
},
"~:id":"~u6191cd35-bb1f-81f7-8004-7cc63d087374"
}
}

File diff suppressed because one or more lines are too long

View file

@ -43,4 +43,18 @@ export class ViewerPage extends BaseWebSocketPage {
async cleanUp() { async cleanUp() {
await this.#ws.mockClose(); await this.#ws.mockClose();
} }
async showComments(clickOptions = {}) {
await this.page
.getByRole("button", { name: "Comments (G C)" })
.click(clickOptions);
}
async showCommentsThread(number, clickOptions = {}) {
await this.page
.getByTestId("floating-thread-bubble")
.filter({ hasText: number.toString() })
.click(clickOptions);
}
} }

View file

@ -111,7 +111,11 @@ export class WorkspacePage extends BaseWebSocketPage {
const layer = this.layers.getByTestId("layer-item").filter({ has: this.page.getByText(name) }); const layer = this.layers.getByTestId("layer-item").filter({ has: this.page.getByText(name) });
await layer.getByRole("button").click(clickOptions); await layer.getByRole("button").click(clickOptions);
} }
async expectSelectedLayer(name) {
await expect(this.layers.getByTestId("layer-row").filter({ has: this.page.getByText(name) })).toHaveClass(/selected/);
}
async clickAssets(clickOptions = {}) { async clickAssets(clickOptions = {}) {
await this.assets.click(clickOptions); await this.assets.click(clickOptions);
} }

View file

@ -0,0 +1,34 @@
import { test, expect } from "@playwright/test";
import { ViewerPage } from "../pages/ViewerPage";
test.beforeEach(async ({ page }) => {
await ViewerPage.init(page);
});
const singleBoardFileId = "dd5cc0bb-91ff-81b9-8004-77df9cd3edb1";
const singleBoardPageId = "dd5cc0bb-91ff-81b9-8004-77df9cd3edb2";
const setupFileWithSingleBoard = async (viewer) => {
await viewer.mockRPC(/get\-view\-only\-bundle\?/, "viewer/get-view-only-bundle-single-board.json");
await viewer.mockRPC("get-comment-threads?file-id=*", "workspace/get-comment-threads-not-empty.json");
await viewer.mockRPC(
"get-file-fragment?file-id=*&fragment-id=*",
"viewer/get-file-fragment-single-board.json",
);
await viewer.mockRPC("get-comments?thread-id=*", "workspace/get-thread-comments.json");
await viewer.mockRPC("update-comment-thread-status", "workspace/update-comment-thread-status.json");
};
test("Comment is shown with scroll and valid position", async ({ page }) => {
const viewer = new ViewerPage(page);
await viewer.setupLoggedInUser();
await setupFileWithSingleBoard(viewer);
await viewer.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
await viewer.showComments();
await viewer.showCommentsThread(1);
await expect(viewer.page.getByRole("textbox", { name: "Reply" })).toBeVisible();
await viewer.showCommentsThread(1);
await viewer.showCommentsThread(2);
await expect(viewer.page.getByRole("textbox", { name: "Reply" })).toBeVisible();
});

View file

@ -66,3 +66,19 @@ test("User adds a library and its automatically selected in the color palette",
await expect(workspacePage.palette.getByText('There are no color styles in your library yet')).toBeVisible(); await expect(workspacePage.palette.getByText('There are no color styles in your library yet')).toBeVisible();
}); });
test("User makes a group", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json");
await workspacePage.goToWorkspace({
fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375"
});
await workspacePage.clickLeafLayer("Rectangle");
await workspacePage.page.keyboard.press("ControlOrMeta+g");
await workspacePage.expectSelectedLayer("Group");
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

View file

@ -291,9 +291,7 @@
// INPUTS // INPUTS
.input-base { .input-base {
@include removeInputStyle; @include removeInputStyle;
@include bodySmallTypography;
@include textEllipsis; @include textEllipsis;
// @include focusInput;
height: $s-28; height: $s-28;
width: 100%; width: 100%;
flex-grow: 1; flex-grow: 1;
@ -326,7 +324,6 @@
} }
.input-element { .input-element {
@include bodySmallTypography;
@include focusInput; @include focusInput;
display: flex; display: flex;
align-items: center; align-items: center;

View file

@ -372,6 +372,7 @@
--pill-foreground-color: var(--color-foreground-primary); --pill-foreground-color: var(--color-foreground-primary);
--link-foreground-color: var(--color-accent-primary); --link-foreground-color: var(--color-accent-primary);
--register-confirmation-color: var(--status-color-success-200);
--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);

View file

@ -203,7 +203,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [selected (wsh/lookup-selected state)] (let [selected (wsh/lookup-selected state)]
(rx/of (group-shapes nil selected)))))) (rx/of (group-shapes nil selected :change-selection? true))))))
(defn ungroup-shapes (defn ungroup-shapes
[ids & {:keys [change-selection?] :or {change-selection? false}}] [ids & {:keys [change-selection?] :or {change-selection? false}}]

View file

@ -11,6 +11,7 @@
[app.common.files.changes-builder :as pcb] [app.common.files.changes-builder :as pcb]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.logic.shapes :as cls]
[app.common.types.page :as ctp] [app.common.types.page :as ctp]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.types.shape.interactions :as ctsi] [app.common.types.shape.interactions :as ctsi]
@ -131,8 +132,7 @@
(let [new-interaction (-> ctsi/default-interaction (let [new-interaction (-> ctsi/default-interaction
(ctsi/set-destination destination) (ctsi/set-destination destination)
(assoc :position-relative-to (:id shape)))] (assoc :position-relative-to (:id shape)))]
(update shape :interactions (cls/add-new-interaction shape new-interaction)))))
ctsi/add-interaction new-interaction)))))
(when (and (not (connected-frame? objects (:id frame))) (when (and (not (connected-frame? objects (:id frame)))
(nil? flow)) (nil? flow))
(rx/of (add-flow (:id frame)))))))))) (rx/of (add-flow (:id frame))))))))))

View file

@ -97,7 +97,7 @@
(when cls (when cls
(cond (cond
(true? v) cls (true? v) cls
(false? v) nil (false? v) ""
:else `(if ~v ~cls "")))))) :else `(if ~v ~cls ""))))))
(interpose " "))) (interpose " ")))

View file

@ -15,7 +15,9 @@
[app.main.ui.frame-preview :as frame-preview] [app.main.ui.frame-preview :as frame-preview]
[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.main.ui.onboarding :refer [onboarding-modal]] [app.main.ui.onboarding.newsletter :refer [onboarding-newsletter]]
[app.main.ui.onboarding.questions :refer [questions-modal]]
[app.main.ui.onboarding.team-choice :refer [onboarding-team-modal]]
[app.main.ui.releases :refer [release-notes-modal]] [app.main.ui.releases :refer [release-notes-modal]]
[app.main.ui.static :as static] [app.main.ui.static :as static]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -96,19 +98,43 @@
#_[:& app.main.ui.onboarding/onboarding-modal] #_[:& app.main.ui.onboarding/onboarding-modal]
#_[:& app.main.ui.onboarding.team-choice/onboarding-team-modal] #_[:& app.main.ui.onboarding.team-choice/onboarding-team-modal]
(when-let [props (get profile :props)] (when-let [props (get profile :props)]
(cond (let [show-question-modal?
(and (not (:onboarding-viewed props)) (and (contains? cf/flags :onboarding)
(contains? cf/flags :onboarding)) (not (:onboarding-viewed props))
[:& onboarding-modal {}] (not (contains? props :onboarding-questions)))
(and (contains? cf/flags :onboarding) show-newsletter-modal?
(:onboarding-viewed props) (and (contains? cf/flags :onboarding)
(not= (:release-notes-viewed props) (:main cf/version)) (not (:onboarding-viewed props))
(not= "0.0" (:main cf/version))) (not (contains? props :newsletter-updates))
[:& release-notes-modal {:version (:main cf/version)}])) (contains? props :onboarding-questions))
show-team-modal?
(and (contains? cf/flags :onboarding)
(not (:onboarding-viewed props))
(not (contains? props :onboarding-team-id))
(contains? props :newsletter-updates))
show-release-modal?
(and (contains? cf/flags :onboarding)
(:onboarding-viewed props)
(not= (:release-notes-viewed props) (:main cf/version))
(not= "0.0" (:main cf/version)))]
(cond
show-question-modal?
[:& questions-modal]
show-newsletter-modal?
[:& onboarding-newsletter]
show-team-modal?
[:& onboarding-team-modal]
show-release-modal?
[:& release-notes-modal {:version (:main cf/version)}])))
[:& dashboard-page {:route route :profile profile}]] [:& dashboard-page {:route route :profile profile}]]
:viewer :viewer
(let [{:keys [query-params path-params]} route (let [{:keys [query-params path-params]} route
{:keys [index share-id section page-id interactions-mode frame-id] {:keys [index share-id section page-id interactions-mode frame-id]

View file

@ -44,6 +44,9 @@
{::mf/props :obj} {::mf/props :obj}
[{:keys [route]}] [{:keys [route]}]
(let [section (dm/get-in route [:data :name]) (let [section (dm/get-in route [:data :name])
show-login-icon (and
(not= section :auth-register-validate)
(not= section :auth-register-success))
params (:query-params route) params (:query-params route)
error (:error params)] error (:error params)]
@ -55,8 +58,9 @@
(st/emit! (du/show-redirect-error error)))) (st/emit! (du/show-redirect-error error))))
[:main {:class (stl/css :auth-section)} [:main {:class (stl/css :auth-section)}
[:h1 {:class (stl/css :logo-container)} (when show-login-icon
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]] [:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]])
[:div {:class (stl/css :login-illustration)} [:div {:class (stl/css :login-illustration)}
i/login-illustration] i/login-illustration]

View file

@ -31,6 +31,7 @@
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
width: $s-120; width: $s-120;
height: $s-96;
margin-block-end: $s-52; margin-block-end: $s-52;
} }

View file

@ -10,14 +10,22 @@
width: 100%; width: 100%;
padding-block-end: 0; padding-block-end: 0;
display: grid; display: grid;
gap: $s-24; gap: $s-12;
form { form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: $s-12; gap: $s-12;
margin-top: $s-12;
} }
} }
.auth-title-wrapper {
width: 100%;
padding-block-end: 0;
display: grid;
gap: $s-8;
}
.separator { .separator {
border-color: var(--modal-separator-backogrund-color); border-color: var(--modal-separator-backogrund-color);
margin: 0; margin: 0;

View file

@ -169,7 +169,7 @@
[:& fm/input [:& fm/input
{:name :email {:name :email
:type "email" :type "email"
:label (tr "auth.email") :label (tr "auth.work-email")
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}

View file

@ -80,7 +80,7 @@
: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.work-email")
:type "text" :type "text"
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]

View file

@ -104,7 +104,7 @@
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
[:& fm/input {:type "text" [:& fm/input {:type "text"
:name :email :name :email
:label (tr "auth.email") :label (tr "auth.work-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)}]]
@ -134,11 +134,11 @@
(mf/defc register-page (mf/defc register-page
{::mf/props :obj} {::mf/props :obj}
[{:keys [params]}] [{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper)} [:div {:class (stl/css :auth-form-wrapper :register-form)}
[:h1 {:class (stl/css :auth-title) [:h1 {:class (stl/css :auth-title)
:data-test "registration-title"} (tr "auth.register-title")] :data-test "registration-title"} (tr "auth.register-title")]
[:p {:class (stl/css :auth-tagline)} [:p {:class (stl/css :auth-tagline)}
(tr "auth.login-tagline")] (tr "auth.register-tagline")]
(when (contains? cf/flags :demo-warning) (when (contains? cf/flags :demo-warning)
[:& login/demo-warning]) [:& login/demo-warning])
@ -229,11 +229,11 @@
(mf/html (mf/html
[:& tr-html [:& tr-html
{:tag-name "div" {:tag-name "div"
:label "auth.terms-privacy-agreement-md" :label "auth.terms-and-privacy-agreement"
: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 [:& fm/input {:name :accept-terms-and-privacy
:class "check-primary" :class (stl/css :checkbox-terms-and-privacy)
:type "checkbox" :type "checkbox"
:default-checked false :default-checked false
:label terms-label}]])) :label terms-label}]]))
@ -247,11 +247,12 @@
(mf/defc register-validate-page (mf/defc register-validate-page
[{:keys [params]}] [{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper)} [:div {:class (stl/css :auth-form-wrapper)}
[:h1 {:class (stl/css :auth-title) [:h1 {:class (stl/css :logo-container)}
:data-test "register-title"} (tr "auth.register-title")] [:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")] [:div {:class (stl/css :auth-title-wrapper)}
[:h2 {:class (stl/css :auth-title)
[:hr {:class (stl/css :separator)}] :data-test "register-title"} (tr "auth.register-account-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-account-tagline")]]
[:& register-validate-form {:params params}] [:& register-validate-form {:params params}]
@ -264,7 +265,11 @@
(mf/defc register-success-page (mf/defc register-success-page
[{:keys [params]}] [{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper :register-success)} [:div {:class (stl/css :auth-form-wrapper :register-success)}
[:div {:class (stl/css :notification-icon)} i/icon-verify] [:h1 {:class (stl/css :logo-container)}
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")] [:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[:div {:class (stl/css :auth-title-wrapper)}
[:h2 {:class (stl/css :auth-title)}
(tr "auth.check-mail")]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]]
[:div {:class (stl/css :notification-text-email)} (:email params "")] [:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]]) [:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])

View file

@ -8,15 +8,24 @@
@use "./common.scss"; @use "./common.scss";
.accept-terms-and-privacy-wrapper { .accept-terms-and-privacy-wrapper {
margin: $s-16 0;
:global(a) { :global(a) {
color: $df-secondary; color: $df-secondary;
font-weight: $fw700; font-weight: $fw700;
} }
} }
.checkbox-terms-and-privacy {
align-items: flex-start;
}
.register-form {
gap: $s-24;
}
.register-success { .register-success {
padding-bottom: $s-32; gap: $s-24;
.auth-title {
@include medTitleTipography;
}
} }
.notification-icon { .notification-icon {
@ -30,9 +39,30 @@
} }
} }
.notification-text-email,
.notification-text { .notification-text {
font-size: $fs-16; @include bodyMediumTypography;
color: var(--notification-foreground-color-default); color: var(--title-foreground-color);
margin-bottom: $s-16; }
.notification-text-email {
@include medTitleTipography;
font-size: $fs-20;
color: var(--register-confirmation-color);
margin-inline: $s-36;
}
.logo-btn {
height: $s-40;
svg {
width: $s-120;
height: $s-40;
fill: var(--main-icon-foreground);
}
}
.logo-container {
display: flex;
justify-content: flex-start;
width: $s-120;
margin-block-end: $s-24;
} }

View file

@ -181,6 +181,7 @@
[:* [:*
[:div [:div
{:class (stl/css :floating-thread-bubble) {:class (stl/css :floating-thread-bubble)
:data-testid "floating-thread-bubble"
: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}
@ -435,9 +436,9 @@
[:* {: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}]] [:& reply-form {:thread thread}]
[:& reply-form {:thread thread}]]))) [:div {:ref ref}]])))
(defn use-buble (defn use-buble
[zoom {:keys [position frame-id]}] [zoom {:keys [position frame-id]}]
@ -558,6 +559,7 @@
: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
:data-testid "floating-thread-bubble"
:class (stl/css-case :class (stl/css-case
:floating-thread-bubble true :floating-thread-bubble true
:resolved (:is-resolved thread) :resolved (:is-resolved thread)

View file

@ -236,6 +236,7 @@
.reply-form { .reply-form {
textarea { textarea {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
line-height: 1.45; line-height: 1.45;
height: 100%; height: 100%;
width: 100%; width: 100%;

View file

@ -117,7 +117,7 @@
[:* [:*
(cond (cond
(some? label) (some? label)
[:label {:class (stl/css-case :input-with-label (not is-checkbox?) [:label {:class (stl/css-case :input-with-label-form (not is-checkbox?)
:input-label is-text? :input-label is-text?
:radio-label is-radio? :radio-label is-radio?
:checkbox-label is-checkbox?) :checkbox-label is-checkbox?)
@ -214,7 +214,7 @@
[:span {:class (stl/css :hint)} hint])])) [:span {:class (stl/css :hint)} hint])]))
(mf/defc select (mf/defc select
[{:keys [options disabled form default dropdown-class] :as props [{:keys [options disabled form default dropdown-class select-class] :as props
:or {default ""}}] :or {default ""}}]
(let [input-name (get props :name) (let [input-name (get props :name)
form (or form (mf/use-ctx form-ctx)) form (or form (mf/use-ctx form-ctx))
@ -230,6 +230,7 @@
{:default-value value {:default-value value
:disabled disabled :disabled disabled
:options options :options options
:class select-class
:dropdown-class dropdown-class :dropdown-class dropdown-class
:on-change handle-change}]])) :on-change handle-change}]]))
@ -297,6 +298,71 @@
:value value' :value value'
:checked checked?}]]))])) :checked checked?}]]))]))
(mf/defc image-radio-buttons
{::mf/wrap-props false}
[props]
(let [form (or (unchecked-get props "form")
(mf/use-ctx form-ctx))
name (unchecked-get props "name")
image (unchecked-get props "image")
img-height (unchecked-get props "img-height")
img-width (unchecked-get props "img-width")
current-value (or (dm/get-in @form [:data name] "")
(unchecked-get props "value"))
on-change (unchecked-get props "on-change")
options (unchecked-get props "options")
trim? (unchecked-get props "trim")
class (unchecked-get props "class")
encode-fn (d/nilv (unchecked-get props "encode-fn") identity)
decode-fn (d/nilv (unchecked-get props "decode-fn") identity)
on-change'
(mf/use-fn
(mf/deps on-change form name)
(fn [event]
(let [value (-> event dom/get-target dom/get-value decode-fn)]
(when (some? form)
(swap! form assoc-in [:touched name] true)
(fm/on-input-change form name value trim?))
(when (fn? on-change)
(on-change name value)))))]
[:div {:class (if image
class
(dm/str class " " (stl/css :custom-radio)))}
(for [{:keys [image icon value label area]} options]
(let [icon? (some? icon)
value' (encode-fn value)
checked? (= value current-value)
key (str/ffmt "%-%" (d/name name) (d/name value'))]
[:label {:for key
:key key
:style {:grid-area area}
:class (stl/css-case :radio-label-image true
:global/checked checked?)}
(cond
icon?
[:span {:class (stl/css :icon-inside)
:style {:height img-height
:width img-width}} icon]
:else
[:span {:style {:background-image (str/ffmt "url(%)" image)
:height img-height
:width img-width}
:class (stl/css :image-inside)}])
[:span {:class (stl/css :image-text)} label]
[:input {:on-change on-change'
:type "radio"
:class (stl/css :radio-input)
:id key
:name name
:value value'
:checked checked?}]]))]))
(mf/defc submit-button* (mf/defc submit-button*
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [on-click children label form class name disabled] :as props}] [{:keys [on-click children label form class name disabled] :as props}]
@ -378,6 +444,7 @@
:no-padding (pos? (count @items)) :no-padding (pos? (count @items))
:invalid (and (some? valid-item-fn) :invalid (and (some? valid-item-fn)
touched? touched?
(not (str/empty? @value))
(not (valid-item-fn @value))))) (not (valid-item-fn @value)))))
on-focus on-focus

View file

@ -38,10 +38,9 @@
} }
} }
.input-with-label { .input-with-label-form {
@include flexColumn; @include flexColumn;
gap: $s-8; gap: $s-8;
@include bodySmallTypography;
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
height: 100%; height: 100%;
@ -55,6 +54,7 @@
color: var(--input-foreground-color-active); color: var(--input-foreground-color-active);
margin-top: 0; margin-top: 0;
width: 100%; width: 100%;
max-width: 100%;
height: 100%; height: 100%;
padding: 0 $s-8; padding: 0 $s-8;
@ -64,6 +64,7 @@
border-radius: $br-8; border-radius: $br-8;
} }
} }
// Input autofill // Input autofill
input:-webkit-autofill, input:-webkit-autofill,
input:-webkit-autofill:hover, input:-webkit-autofill:hover,
@ -169,6 +170,10 @@
border-color: var(--input-checkbox-border-color-hover); border-color: var(--input-checkbox-border-color-hover);
} }
} }
a {
// Need for terms and conditions links on register checkbox
color: var(--link-foreground-color);
}
} }
} }
@ -367,7 +372,7 @@
height: fit-content; height: fit-content;
border-radius: $br-8; border-radius: $br-8;
padding: $s-8; padding: $s-8;
color: var(--input-foreground-color); color: var(--input-foreground-color-rest);
border: $s-1 solid transparent; border: $s-1 solid transparent;
&:focus, &:focus,
&:focus-within { &:focus-within {
@ -393,14 +398,12 @@
border-radius: $br-circle; border-radius: $br-circle;
} }
.radio-label.with-image { .radio-label-image {
@include smallTitleTipography; @include smallTitleTipography;
display: grid; display: grid;
grid-template-rows: auto auto 0px; grid-template-rows: auto auto 0px;
justify-items: center; justify-items: center;
gap: 0; gap: 0;
height: $s-116;
width: $s-92;
border-radius: $br-8; border-radius: $br-8;
margin: 0; margin: 0;
border: 1px solid var(--color-background-tertiary); border: 1px solid var(--color-background-tertiary);
@ -413,22 +416,29 @@
outline: none; outline: none;
border: $s-1 solid var(--input-border-color-active); border: $s-1 solid var(--input-border-color-active);
} }
.image-text {
color: var(--input-foreground-color-rest);
display: grid;
align-self: center;
margin-bottom: $s-16;
padding-inline: $s-8;
text-align: center;
}
} }
.image-inside { .image-inside {
width: $s-60; margin: $s-16;
height: $s-48; background-size: 100%;
background-size: $s-48;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
} }
.icon-inside { .icon-inside {
width: $s-60; margin: $s-16;
height: $s-48; @include flexCenter;
svg { svg {
width: $s-60; width: 40px;
height: $s-48; height: 60px;
stroke: var(--icon-foreground); stroke: var(--icon-foreground);
fill: none; fill: none;
} }

View file

@ -34,6 +34,7 @@
.input-wrapper { .input-wrapper {
@extend .input-with-label; @extend .input-with-label;
@include bodySmallTypography;
} }
.action-buttons { .action-buttons {

View file

@ -81,6 +81,7 @@
} }
.file-name-edit { .file-name-edit {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
flex-grow: 1; flex-grow: 1;
} }
.file-name-label { .file-name-label {

View file

@ -540,5 +540,6 @@
.email-input { .email-input {
@extend .input-base; @extend .input-base;
@include bodySmallTypography;
height: auto; height: auto;
} }

View file

@ -37,6 +37,7 @@
.group-name-input { .group-name-input {
@extend .input-element-label; @extend .input-element-label;
@include bodySmallTypography;
margin-bottom: $s-8; margin-bottom: $s-8;
label { label {
@include flexColumn; @include flexColumn;

View file

@ -93,6 +93,7 @@
} }
.input-wrapper { .input-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
} }
} }
} }

View file

@ -1,161 +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
(ns app.main.ui.onboarding
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.config :as cf]
[app.main.data.events :as ev]
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.onboarding.newsletter]
[app.main.ui.onboarding.questions]
[app.main.ui.onboarding.team-choice]
[app.main.ui.onboarding.templates]
[app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as tm]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
;; --- ONBOARDING LIGHTBOX
(defn send-event
[event-name]
(st/emit! (ptk/event ::ev/event {::ev/name event-name
::ev/origin "dashboard"})))
(mf/defc onboarding-welcome
[{:keys [next] :as props}]
(let [go-next
(fn []
(send-event "onboarding-step1-continue")
(next))]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/welcomeilustration.svg"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:h1 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.welcome.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.welcome.desc1")]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://community.penpot.app/"
:target "_blank"
:on-click #(send-event "onboarding-community-link")}
(tr "onboarding-v2.welcome.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc2")]]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-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 {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc3")]]
[:button {:on-click go-next
:class (stl/css :accept-btn)
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]))
(mf/defc onboarding-before-start
[{:keys [next] :as props}]
(let [go-next
(fn []
(send-event "onboarding-step2-continue")
(next))]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/beforeyoustartilustration.svg"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:h1 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.before-start.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.before-start.desc1")]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
: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 {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc2")]]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
: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 {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc3")]]
[:button {:on-click go-next
:class (stl/css :accept-btn)
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]))
(mf/defc onboarding-modal
{::mf/register modal/components
::mf/register-as :onboarding}
[_]
(let [slide (mf/use-state :start)
klass (mf/use-state "fadeInDown")
navigate
(mf/use-fn #(reset! slide %))
skip
(mf/use-fn
(fn []
(st/emit! (modal/hide)
(du/mark-onboarding-as-viewed))
(cond
(contains? cf/flags :onboarding-questions)
(modal/show! {:type :onboarding-questions})
(contains? cf/flags :onboarding-newsletter)
(modal/show! {:type :onboarding-newsletter})
(contains? cf/flags :onboarding-team)
(modal/show! {:type :onboarding-team}))))
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")]
(mf/with-effect [@slide]
(when (not= :start @slide)
(reset! klass "fadeIn"))
(let [sem (tm/schedule 300 #(reset! klass nil))]
(fn []
(reset! klass nil)
(tm/dispose! sem))))
[:div {:class (stl/css-case :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div.animated {:class (dm/str @klass " " (stl/css :animated))}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]]))

View file

@ -1,86 +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
@import "refactor/common-refactor.scss";
.modal-overlay {
@extend .modal-overlay-base;
}
.modal-container {
@extend .modal-container-base;
position: relative;
display: grid;
grid-template-columns: auto auto;
gap: $s-32;
padding-inline: $s-100;
padding-block-start: $s-100;
padding-block-end: $s-72;
margin: 0;
width: $s-960;
height: $s-632;
max-width: $s-960;
max-height: $s-632;
}
.modal-left {
width: $s-240;
margin-block-end: $s-64;
img {
width: $s-240;
height: 100%;
border-radius: $br-8 0 0 $br-8;
}
}
.modal-right {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: $s-40 auto auto auto $s-32;
gap: $s-24;
position: relative;
}
.release {
@include bodySmallTypography;
position: absolute;
top: calc(-1 * $s-28);
right: 0;
padding: $s-8;
color: var(--modal-text-foreground-color);
}
.modal-title {
@include bigTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-text,
.property-description {
@include bodyLargeTypography;
margin: 0;
color: var(--modal-text-foreground-color);
}
.modal-link {
@include bodyLargeTypography;
color: var(--modal-link-foreground-color);
margin: 0;
}
.text-wrapper {
@include flexColumn;
}
.property-title a {
@include medTitleTipography;
color: var(--modal-title-foreground-color);
}
.accept-btn {
@extend .modal-accept-btn;
justify-self: flex-end;
}

View file

@ -8,39 +8,52 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.config :as cf] [app.config :as cf]
[app.main.data.events :as-alias ev]
[app.main.data.messages :as msg] [app.main.data.messages :as msg]
[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.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]]
[potok.v2.core :as ptk]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc onboarding-newsletter (mf/defc onboarding-newsletter
{::mf/register modal/components
::mf/register-as :onboarding-newsletter}
[] []
(let [message (tr "onboarding.newsletter.acceptance-message") (let [state* (mf/use-state #(do {:newsletter-updates false
newsletter-updates (mf/use-state false) :newsletter-news false}))
newsletter-news (mf/use-state false) state (deref state*)
toggle
(mf/use-callback
(fn [option]
(swap! option not)))
on-change
(mf/use-fn
(fn [event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(swap! state* update attr not))))
accept on-next
(mf/use-callback (mf/use-fn
(mf/deps @newsletter-updates @newsletter-news) (mf/deps state)
(fn [] (fn []
(st/emit! (when (or @newsletter-updates @newsletter-news) (when (or (:newsletter-updates state)
(msg/success message)) (:newsletter-news state))
(modal/show {:type :onboarding-team}) (st/emit! (msg/success (tr "onboarding.newsletter.acceptance-message"))))
(du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")] (let [params (-> state
(assoc ::ev/name "onboarding-step")
(assoc :label "newsletter:subscriptions")
(assoc :step 6))]
(st/emit! (ptk/data-event ::ev/event params)
(du/update-profile-props state)))))
onboarding-a-b-test?
(cf/external-feature-flag "signup-background" "test")]
[:div {:class (stl/css-case
:modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div {:class (stl/css-case :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div.animated.fadeInDown {:class (stl/css :modal-container)} [:div.animated.fadeInDown {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)} [:div {:class (stl/css :modal-left)}
[:img {:src "images/deco-newsletter.png" [:img {:src "images/deco-newsletter.png"
@ -50,30 +63,34 @@
[: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 :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 state))}
(when @newsletter-updates i/status-tick]
i/status-tick)]
(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)}]]] :data-attr "newsletter-updates"
:value (:newsletter-updates state)
:on-change on-change}]]]
[: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 state))}
(when @newsletter-news i/status-tick]
i/status-tick)]
(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)}]]]] :data-attr "newsletter-news"
:value (:newsletter-news state)
:on-change on-change}]]]]
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy1") (tr "onboarding-v2.newsletter.privacy1")
@ -84,5 +101,6 @@
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy2")] (tr "onboarding-v2.newsletter.privacy2")]
[:button {:on-click accept [:button {:on-click on-next
:class (stl/css :accept-btn)} (tr "labels.continue")]]]])) :class (stl/css :accept-btn)}
(tr "labels.continue")]]]]))

View file

@ -11,7 +11,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.config :as cf] [app.config :as cf]
[app.main.data.modal :as modal] [app.main.data.events :as-alias ev]
[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]
@ -19,223 +19,430 @@
[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]
[potok.v2.core :as ptk]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc step-container (mf/defc step-container
[{:keys [form step on-next on-prev children class] :as props}] {::mf/props :obj}
[{:keys [form step on-next on-prev children class label]}]
[:& fm/form {:form form :on-submit on-next :class (dm/str class " " (stl/css :form-wrapper))} (let [on-next*
[:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)] (mf/use-fn
(mf/deps on-next step label)
(fn [form event]
(let [params (-> (:clean-data @form)
(assoc :label label)
(assoc :step step)
(assoc ::ev/name "onboarding-step"))]
(st/emit! (ptk/data-event ::ev/event params))
(on-next form event))))]
children [:& fm/form {:form form
:on-submit on-next*
:class (dm/str class " " (stl/css :form-wrapper))}
[:div {:class (stl/css :paginator)} (str/ffmt "%/5" step)]
[:div {:class (stl/css :action-buttons)} children
(when on-prev [:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :prev-button)
:on-click on-prev} (tr "questions.previous")])
[:> fm/submit-button* (when (some? on-prev)
{:label (if (< step 4) (tr "questions.next") (tr "questions.start")) [:button {:class (stl/css :prev-button)
:class (stl/css :next-button)}]]]) :on-click on-prev}
(tr "questions.previous")])
[:> fm/submit-button*
{:label (if (< step 5)
(tr "questions.next")
(tr "questions.start"))
:class (stl/css :next-button)}]]]))
(s/def ::questions-form-step-1 (s/def ::questions-form-step-1
(s/keys :req-un [::planning])) (s/keys :req-un [::planning
::expected-use]
(mf/defc step-1 :opt-un [::planning-other]))
[{:keys [on-next form] :as props}]
[:& step-container {:form form :step 1 :on-next on-next :class (stl/css :step-1)}
[:img {:class (stl/css :header-image)
:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
[:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")]
[:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (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
:dropdown-class (stl/css :question-dropdown)}]]])
(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]))
(mf/defc step-2
[{:keys [on-next on-prev form] :as props}]
[:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev :class (stl/css :step-2)}
[:h1 {:class (stl/css :modal-title)}
(tr "questions.describe-your-experience-working-on")]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(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
:class (stl/css :radio-btns)}]]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(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
:class (stl/css :radio-btns)}]]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(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
:class (stl/css :radio-btns)}]]])
(s/def ::questions-form-step-3
(s/keys :req-un [::experience-design-tool]
:opt-un [::experience-design-tool-other]))
(defn- step-1-form-validator (defn- step-1-form-validator
[errors data] [errors data]
(let [planning (-> (:planning data) (str/trim))] (let [planning (:planning data)
planning-other (:planning-other data)]
(cond-> errors (cond-> errors
(= planning "") (and (= planning "other")
(str/blank? planning-other))
(assoc :planning-other {:code "missing"})
(not= planning "other")
(assoc :planning-other nil)
(str/blank? planning)
(assoc :planning {:code "missing"})))) (assoc :planning {:code "missing"}))))
(mf/defc step-1
{::mf/props :obj}
[{:keys [on-next form]}]
(let [use-options
(mf/with-memo []
(shuffle [{:label (tr "questions.use-work") :value "use-work"}
{:label (tr "questions.use-education") :value "use-education"}
{:label (tr "questions.use-personal") :value "use-personal"}]))
planning-options
(mf/with-memo []
(-> (shuffle [{:label (tr "questions.select-option")
:value "" :key "questions:what-brings-you-here"
:disabled true}
{:label (tr "questions.reasons.exploring")
:value "discover-more-about-penpot"
:key "discover-more-about-penpot"}
{:label (tr "questions.reasons.fit")
: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.reasons.alternative")
:value "alternative-to-figma"
:key "alternative-to-figma"}
{:label (tr "questions.reasons.testing")
:value "try-out-before-using-penpot-on-premise"
:key "try-out-before-using-penpot-on-premise"}])
(conj {:label (tr "questions.other-short") :value "other"})))
current-planning
(dm/get-in @form [:data :planning])]
[:& step-container {:form form
:step 1
:label "questions:about-you"
:on-next on-next
:class (stl/css :step-1)}
[:img {:class (stl/css :header-image)
:src "images/form/use-for-1.png"
:alt (tr "questions.lets-get-started")}]
[:h1 {:class (stl/css :modal-title)}
(tr "questions.step1-title")]
[:p {:class (stl/css :modal-text)}
(tr "questions.step1-subtitle")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)}
(tr "questions.step1-question1")]
[:& fm/radio-buttons {:options use-options
:name :expected-use
:class (stl/css :radio-btns)}]
[:h3 {:class (stl/css :modal-subtitle)}
(tr "questions.step1-question2")]
[:& fm/select
{:options planning-options
:select-class (stl/css :select-class)
:default ""
:name :planning
:dropdown-class (stl/css :question-dropdown)}]
(when (= current-planning "other")
[:& fm/input {:name :planning-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]]))
(s/def ::questions-form-step-2
(s/keys :req-un [::experience-design-tool]
:opt-un [::experience-design-tool-other]))
(defn- step-2-form-validator
[errors data]
(let [experience (:experience-design-tool data)
experience-other (:experience-design-tool-other data)]
(cond-> errors
(and (= experience "other")
(str/blank? experience-other))
(assoc :experience-design-tool-other {:code "missing"})
(not= experience "other")
(assoc :experience-design-tool-other nil))))
(mf/defc step-2
{::mf/props :obj}
[{:keys [on-next on-prev form]}]
(let [design-tool-options
(mf/with-memo []
(-> (shuffle [{:label (tr "questions.figma") :img-width "48px" :img-height "60px"
:value "figma" :image "images/form/figma.png"}
{:label (tr "questions.sketch") :img-width "48px" :img-height "60px"
:value "sketch" :image "images/form/sketch.png"}
{:label (tr "questions.adobe-xd") :img-width "48px" :img-height "60px"
:value "adobe-xd" :image "images/form/adobe-xd.png"}
{:label (tr "questions.canva") :img-width "48px" :img-height "60px"
:value "canva" :image "images/form/canva.png"}
{:label (tr "questions.invision") :img-width "48px" :img-height "60px"
:value "invision" :image "images/form/invision.png"}])
(conj {:label (tr "questions.other-short") :value "other" :icon i/curve})))
current-experience
(dm/get-in @form [:clean-data :experience-design-tool])
on-design-tool-change
(mf/use-fn
(mf/deps current-experience)
(fn []
(when (not= current-experience "other")
(swap! form d/dissoc-in [:data :experience-design-tool-other])
(swap! form d/dissoc-in [:errors :experience-design-tool-other]))))]
[:& step-container {:form form
:step 2
:label "questions:experience-design-tool"
:on-next on-next
:on-prev on-prev
:class (stl/css :step-2)}
[:h1 {:class (stl/css :modal-title)}
(tr "question.design-tool-more-used")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/image-radio-buttons {:options design-tool-options
:img-width "48px"
:img-height "60px"
:name :experience-design-tool
:image true
:class (stl/css :image-radio)
:on-change on-design-tool-change}]
(when (= current-experience "other")
[:& fm/input {:name :experience-design-tool-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]]))
(s/def ::questions-form-step-3
(s/keys :req-un [::team-size ::role ::responsability]
:opt-un [::role-other ::responsability-other]))
(defn- step-3-form-validator (defn- step-3-form-validator
[errors data] [errors data]
(let [experience-design-tool (:experience-design-tool data) (let [role (:role data)
experience-design-tool-other (-> (:experience-design-tool-other data) str/trim)] role-other (:role-other data)
responsability (:responsability data)
responsability-other (:responsability-other data)]
(cond-> errors (cond-> errors
(and (= experience-design-tool "other") (= 0 (count experience-design-tool-other))) (and (= role "other")
(assoc :experience-design-tool-other {:code "missing"})))) (str/blank? role-other))
(assoc :role-other {:code "missing"})
(not= role "other")
(assoc :role-other nil)
(and (= responsability "other")
(str/blank? responsability-other))
(assoc :responsability-other {:code "missing"})
(not= responsability "other")
(assoc :responsability-other nil))))
(mf/defc step-3 (mf/defc step-3
[{:keys [on-next on-prev form] :as props}] {::mf/props :obj}
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool]) [{:keys [on-next on-prev form]}]
on-design-tool-change (let [role-options
(fn [_ _] (mf/with-memo []
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])] (-> (shuffle [{:label (tr "questions.select-option") :value "" :key "role" :disabled true}
(when (not= experience-design-tool "other") {:label (tr "questions.work-type.ux") :value "designer" :key "designer"}
(do {:label (tr "questions.work-type.dev") :value "developer" :key "developer"}
(swap! form d/dissoc-in [:data :experience-design-tool-other]) {:label (tr "questions.work-type.student") :value "student-teacher" :key "student"}
(swap! form d/dissoc-in [:errors :experience-design-tool-other])))))] {:label (tr "questions.work-type.graphic") :value "graphic-design" :key "design"}
{:label (tr "questions.work-type.marketing") :value "marketing" :key "marketing"}
{:label (tr "questions.work-type.product") :value "manager" :key "manager"}])
(conj {:label (tr "questions.other-short") :value "other"})))
[:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev :class (stl/css :step-3)} responsability-options
[:h1 {:class (stl/css :modal-title)} (mf/with-memo []
(tr "question.design-tool-more-experienced-with")] (-> (shuffle [{:label (tr "questions.select-option") :value "" :key "responsability" :disabled true}
[:div {:class (stl/css :radio-wrapper)} {:label (tr "questions.role.team-leader") :value "team-leader"}
[:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png" :area "image1"} {:label (tr "questions.role.team-member") :value "team-member"}
{:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png" :area "image2"} {:label (tr "questions.role.freelancer") :value "freelancer"}
{:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png" :area "image3"} {:label (tr "questions.role.founder") :value "ceo-founder"}
{:label (tr "questions.canva") :value "canva" :image "images/form/canva.png" :area "image4"} {:label (tr "questions.role.director") :value "director"}
{:label (tr "questions.invision") :value "invision" :image "images/form/invision.png" :area "image5"} {:label (tr "questions.student-teacher") :value "student-teacher"}])
{:label (tr "questions.never-used-one") :area "image6" :value "never-used-a-tool" :icon i/curve} (conj {:label (tr "questions.other-short") :value "other"})))
{:label (tr "questions.other") :value "other" :area "other"}]
:name :experience-design-tool
:image true
:class (stl/css :image-radio)
:on-change on-design-tool-change}]
[:& fm/input {:name :experience-design-tool-other
:class (stl/css :input-spacing) team-size-options
:placeholder (tr "questions.other") (mf/with-memo []
:label "" [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
:disabled (not= experience-design-tool "other")}]]])) {: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"}])
current-role
(dm/get-in @form [:data :role])
current-responsability
(dm/get-in @form [:data :responsability])]
[:& step-container {:form form
:step 3
:label "questions:about-your-job"
:on-next on-next
:on-prev on-prev
:class (stl/css :step-3)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step3-title")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step3.question1")]
[:& fm/select {:options role-options
:select-class (stl/css :select-class)
:default ""
:name :role}]
(when (= current-role "other")
[:& fm/input {:name :role-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step3.question2")]
[:& fm/select {:options responsability-options
:select-class (stl/css :select-class)
:default ""
:name :responsability}]
(when (= current-responsability "other")
[:& fm/input {:name :responsability-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.company-size")]
[:& fm/select {:options team-size-options
:default ""
:select-class (stl/css :select-class)
:name :team-size}]]]))
(s/def ::questions-form-step-4 (s/def ::questions-form-step-4
(s/keys :req-un [::team-size ::role] (s/keys :req-un [::start-with]
:opt-un [::role-other])) :opt-un [::start-with-other]))
(defn- step-4-form-validator (defn- step-4-form-validator
[errors data] [errors data]
(let [role (:role data) (let [start (:start-with data)
role-other (-> (:role-other data) str/trim)] start-other (:start-with-other data)]
(cond-> errors (cond-> errors
(and (= role "other") (= 0 (count role-other))) (and (= start "other")
(assoc :role-other {:code "missing"})))) (str/blank? start-other))
(assoc :start-with-other {:code "missing"})
(not= start "other")
(assoc :start-with-other nil))))
(mf/defc step-4 (mf/defc step-4
[{:keys [on-next on-prev form] :as props}] {::mf/props :obj}
(let [role (dm/get-in @form [:data :role]) [{:keys [on-next on-prev form]}]
on-role-change (let [start-options
(fn [_ _] (mf/with-memo []
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])] (-> (shuffle [{:label (tr "questions.starting-ui") :value "ui" :image "images/form/Design.png"}
(when (not= experience-design-tool "other") {:label (tr "questions.starting-wireframing") :value "wireframing" :image "images/form/templates.png"}
(do {:label (tr "questions.starting-prototyping") :value "prototyping" :image "images/form/Prototype.png"}
(swap! form d/dissoc-in [:data :role-other]) {:label (tr "questions.starting-ds") :value "ds" :image "images/form/components.png"}
(swap! form d/dissoc-in [:errors :role-other])))))] {:label (tr "questions.starting-code") :value "code" :image "images/form/design-and-dev.png"}])
(conj {:label (tr "questions.other-short") :value "other" :icon i/curve})))
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev :class (stl/css :step-4)} current-start (dm/get-in @form [:data :start-with])
[:h1 {:class (stl/css :modal-title)} (tr "questions.role")]
on-start-change
(mf/use-fn
(mf/deps current-start)
(fn [_ _]
(when (not= current-start "other")
(swap! form d/dissoc-in [:data :start-with-other])
(swap! form d/dissoc-in [:errors :start-with-other]))))]
[:& step-container {:form form
:step 4
:label "questions:how-start"
:on-next on-next
:on-prev on-prev
:class (stl/css :step-4)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step4-title")]
[:div {:class (stl/css :radio-wrapper)} [:div {:class (stl/css :radio-wrapper)}
[:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"} [:& fm/image-radio-buttons {:options start-options
{:label (tr "questions.developer") :value "developer"} :img-width "159px"
{:label (tr "questions.manager") :value "manager"} :img-height "120px"
{:label (tr "questions.founder") :value "founder"} :class (stl/css :image-radio)
{:label (tr "questions.marketing") :value "marketing"} :name :start-with
{:label (tr "questions.student-teacher") :value "student-teacher"} :on-change on-start-change}]
{:label (tr "questions.other") :value "other"}]
:name :role
:on-change on-role-change}]
[:& fm/input {:name :role-other
:class (stl/css :input-spacing)
:label ""
:placeholder (tr "questions.other")
:disabled (not= role "other")}]]
[:div {:class (stl/css :modal-question)} (when (= current-start "other")
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")] [:& fm/input {:name :start-with-other
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true} :class (stl/css :input-spacing)
{:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"} :label ""
{:label (tr "questions.31-50") :value "31-50" :key "31-50"} :placeholder (tr "questions.other")}])]]))
{: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}]]]))
;; NOTE: we don't register it on registry modal because we reference (s/def ::questions-form-step-5
;; this modal directly on the ui namespace. (s/keys :req-un [::referer]
:opt-un [::referer-other]))
(defn- step-5-form-validator
[errors data]
(let [referer (:referer data)
referer-other (:referer-other data)]
(cond-> errors
(and (= referer "other")
(str/blank? referer-other))
(assoc :referer-other {:code "missing"})
(not= referer "other")
(assoc :referer-other nil))))
(mf/defc step-5
{::mf/props :obj}
[{:keys [on-next on-prev form]}]
(let [referer-options
(mf/with-memo []
(-> (shuffle [{:label (tr "questions.referer.youtube") :value "youtube"}
{:label (tr "questions.referer.event") :value "event"}
{:label (tr "questions.referer.search") :value "search"}
{:label (tr "questions.referer.social") :value "social"}
{:label (tr "questions.referer.article") :value "article"}])
(conj {:label (tr "questions.other-short") :value "other"})))
current-referer
(dm/get-in @form [:data :referer])
on-referer-change
(mf/use-fn
(mf/deps current-referer)
(fn []
(when (not= current-referer "other")
(swap! form d/dissoc-in [:data :referer-other])
(swap! form d/dissoc-in [:errors :referer-other]))))]
[:& step-container {:form form
:step 5
:label "questions:referer"
:on-next on-next
:on-prev on-prev
:class (stl/css :step-5)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step5-title")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/radio-buttons {:options referer-options
:class (stl/css :radio-btns)
:name :referer
:on-change on-referer-change}]
(when (= current-referer "other")
[:& fm/input {:name :referer-other
:class (stl/css :input-spacing)
:label ""
:placeholder (tr "questions.other")}])]]))
(mf/defc questions-modal (mf/defc questions-modal
{::mf/register modal/components
::mf/register-as :onboarding-questions}
[] []
(let [container (mf/use-ref) (let [container (mf/use-ref)
step (mf/use-state 1) step (mf/use-state 1)
@ -247,9 +454,12 @@
:initial {} :initial {}
:validators [step-1-form-validator] :validators [step-1-form-validator]
:spec ::questions-form-step-1) :spec ::questions-form-step-1)
step-2-form (fm/use-form step-2-form (fm/use-form
:initial {} :initial {}
:validators [step-2-form-validator]
:spec ::questions-form-step-2) :spec ::questions-form-step-2)
step-3-form (fm/use-form step-3-form (fm/use-form
:initial {} :initial {}
:validators [step-3-form-validator] :validators [step-3-form-validator]
@ -260,6 +470,11 @@
:validators [step-4-form-validator] :validators [step-4-form-validator]
:spec ::questions-form-step-4) :spec ::questions-form-step-4)
step-5-form (fm/use-form
:initial {}
:validators [step-5-form-validator]
:spec ::questions-form-step-5)
on-next on-next
(mf/use-fn (mf/use-fn
(fn [form] (fn [form]
@ -275,27 +490,22 @@
(mf/use-fn (mf/use-fn
(mf/deps @clean-data) (mf/deps @clean-data)
(fn [form] (fn [form]
(let [questionnaire (merge @clean-data (:clean-data @form))] (let [data (merge @clean-data (:clean-data @form))]
(reset! clean-data questionnaire) (reset! clean-data data)
(st/emit! (du/mark-questions-as-answered questionnaire)) (st/emit! (du/mark-questions-as-answered data)))))
(cond onboarding-a-b-test?
(contains? cf/flags :onboarding-newsletter) (cf/external-feature-flag "signup-background" "test")]
(modal/show! {:type :onboarding-newsletter})
(contains? cf/flags :onboarding-team) [:div {:class (stl/css-case
(modal/show! {:type :onboarding-team}) :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
:else
(modal/hide!)))))
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")]
[:div {:class (stl/css-case :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[: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-next :on-prev on-prev :form step-4-form}]
5 [:& step-5 {:on-next on-submit :on-prev on-prev :form step-5-form}])]]))

View file

@ -11,9 +11,9 @@
} }
.modal-container { .modal-container {
max-width: $s-744; max-width: $s-960;
max-height: fit-content; max-height: fit-content;
width: $s-744; width: fit-content;
padding-inline: $s-100; padding-inline: $s-100;
padding-block-start: $s-40; padding-block-start: $s-40;
padding-block-end: $s-72; padding-block-end: $s-72;
@ -47,15 +47,15 @@
@extend .modal-cancel-btn; @extend .modal-cancel-btn;
} }
.radio-btns label,
.select-class span {
@include bodyMediumTypography;
}
// STEP 1 // STEP 1
// .step-1 {
// max-height: $s-468;
// height: $s-468;
// }
.header-image { .header-image {
height: $s-112; height: $s-60;
width: auto; width: auto;
margin-inline-start: auto; margin-inline-start: auto;
} }
@ -81,9 +81,15 @@
} }
// STEP-2 // STEP-2
.step-1,
.step-2,
.step-3,
.step-5 {
max-width: $s-540;
width: $s-540;
}
.step-2 { .step-2 {
grid-template-rows: $s-20 auto auto auto auto $s-32; grid-template-rows: $s-20 auto auto $s-32;
} }
.modal-question { .modal-question {
@ -103,36 +109,36 @@
.radio-wrapper { .radio-wrapper {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: $s-8; gap: $s-16;
} }
// STEP-3 // STEP-3
.step-3 { .step-3 {
grid-template-rows: $s-20 auto auto $s-32; grid-template-rows: $s-20 auto auto auto auto $s-32;
} }
.image-radio { .image-radio {
display: grid; display: grid;
grid-template-rows: 1fr 1fr $s-32; grid-template-rows: 1fr 1fr;
grid-template-columns: $s-88 $s-92 $s-92 $s-92 $s-88; grid-template-columns: $s-92 $s-92 $s-92;
grid-template-areas:
". image1 image2 image3 ."
". image4 image5 image6 ."
"other other other other other";
row-gap: $s-16; row-gap: $s-16;
column-gap: $s-24; column-gap: $s-24;
justify-content: center;
} }
.input-spacing { .input-spacing {
height: $s-32; height: $s-32;
width: calc(100% - $s-24); width: 100%;
margin-inline-start: $s-24;
margin-block-end: $s-8; margin-block-end: $s-8;
} }
.input-spacing input {
@include bodyMediumTypography;
}
// STEP-4 // STEP-4
.step-4 { .step-4 {
grid-template-rows: $s-20 auto auto auto $s-32; grid-template-rows: $s-20 auto auto $s-32;
row-gap: $s-16; row-gap: $s-16;
} }

View file

@ -7,34 +7,29 @@
(ns app.main.ui.onboarding.team-choice (ns app.main.ui.onboarding.team-choice
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data.macros :as dmc] [app.common.data.macros :as dm]
[app.common.spec :as us] [app.common.spec :as us]
[app.config :as cf] [app.config :as cf]
[app.main.data.dashboard :as dd] [app.main.data.dashboard :as dd]
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.data.messages :as msg] [app.main.data.messages :as msg]
[app.main.data.modal :as modal] [app.main.data.users :as du]
[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.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]
[app.util.timers :as tm]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
[potok.v2.core :as ptk] [potok.v2.core :as ptk]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(s/def ::name ::us/not-empty-string) (mf/defc left-sidebar
(s/def ::team-form {::mf/props :obj
(s/keys :req-un [::name])) ::mf/private true}
(mf/defc team-modal-left
[] []
[:div {:class (stl/css :modal-left)} [:div {:class (stl/css :modal-left)}
[:h1 {:class (stl/css :modal-title)} [:h1 {:class (stl/css :modal-title)}
(tr "onboarding-v2.welcome.title")] (tr "onboarding-v2.welcome.title")]
[:h2 {:class (stl/css :modal-subtitle)} [:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.team-definition")] (tr "onboarding.team-modal.team-definition")]
[:p {:class (stl/css :modal-text)} [:p {:class (stl/css :modal-text)}
@ -61,99 +56,27 @@
[:p {:class (stl/css :modal-desc)} [:p {:class (stl/css :modal-desc)}
(tr "onboarding.team-modal.create-team-feature-5")]]]]) (tr "onboarding.team-modal.create-team-feature-5")]]]])
(mf/defc onboarding-team-modal
{::mf/register modal/components
::mf/register-as :onboarding-team}
[]
(let [form (fm/use-form :spec ::team-form
:initial {}
: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"))])
on-submit
(mf/use-fn
(fn [form _]
(let [tname (get-in @form [:clean-data :name])]
(st/emit! (modal/show {:type :onboarding-team-invitations :name tname})
(ptk/event ::ev/event {::ev/name "choose-team-name"
::ev/origin "onboarding"
:name tname
:step 1})))))
on-skip
(fn []
(tm/schedule 400 #(st/emit! (modal/hide)
(ptk/event ::ev/event {::ev/name "create-team-later"
::ev/origin "onboarding"
:step 1}))))
teams (mf/deref refs/teams)
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")]
(mf/with-effect [teams]
(when (> (count teams) 1)
(st/emit! (modal/hide))))
(when (< (count teams) 2)
[:div {:class (stl/css-case :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:& team-modal-left]
[:div {:class (stl/css :separator)}]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :first-block)}
[:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form
:class (stl/css :modal-form)
:on-submit on-submit}
[:& fm/input {:type "text"
:class (stl/css :team-name-input)
:name :name
:placeholder "Team name"
:label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:div {:class (stl/css :action-buttons)}
[:> fm/submit-button*
{:class (stl/css :accept-button)
:label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
[:div {:class (stl/css :second-block)}
[:h2 {:class (stl/css :modal-subtitle)}
(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")]]]]
[:div {:class (stl/css :paginator)} "1/2"]]])))
(defn get-available-roles
[]
[{:value "editor" :label (tr "labels.editor")}
{:value "admin" :label (tr "labels.admin")}])
(s/def ::emails (s/and ::us/set-of-valid-emails)) (s/def ::emails (s/and ::us/set-of-valid-emails))
(s/def ::role ::us/keyword) (s/def ::role ::us/keyword)
(s/def ::invite-form (s/def ::invite-form
(s/keys :req-un [::role ::emails])) (s/keys :req-un [::role ::emails]))
;; This is the final step of team creation, consists in provide a (defn- get-available-roles
;; shortcut for invite users. []
[{:value "editor" :label (tr "labels.editor")}
{:value "admin" :label (tr "labels.admin")}])
(mf/defc team-form-step-2
{::mf/props :obj}
[{:keys [name on-back]}]
(let [initial (mf/use-memo
#(do {:role "editor"
:name name}))
(mf/defc onboarding-team-invitations-modal
{::mf/register modal/components
::mf/register-as :onboarding-team-invitations
::mf/props :obj}
[{:keys [name]}]
(let [initial (mf/use-memo (constantly
{:role "editor"
:name name}))
form (fm/use-form :spec ::invite-form form (fm/use-form :spec ::invite-form
:initial initial) :initial initial)
params (:clean-data @form) params (:clean-data @form)
emails (:emails params) emails (:emails params)
@ -161,51 +84,48 @@
on-success on-success
(mf/use-fn (mf/use-fn
(fn [_form response] (fn [response]
(let [team-id (:id response)] (let [team-id (:id response)]
(st/emit! (st/emit! (du/update-profile-props {:onboarding-team-id team-id
(modal/hide) :onboarding-viewed true})
(rt/nav :dashboard-projects {:team-id team-id})) (rt/nav :dashboard-projects {:team-id team-id})))))
(tm/schedule 400 #(st/emit!
(modal/hide))))))
on-error on-error
(mf/use-fn (mf/use-fn
(fn [_form _cause] (fn [_]
(st/emit! (msg/error "Error on creating team.")))) (st/emit! (msg/error (tr "errors.generic")))))
;; The SKIP branch only creates the team, without invitations
on-invite-later on-invite-later
(mf/use-fn (mf/use-fn
(fn [_] (fn [{:keys [name]}]
(let [mdata {:on-success (partial on-success form) (let [mdata {:on-success on-success
:on-error (partial on-error form)} :on-error on-error}
params {:name name}] params {:name name}]
(st/emit! (dd/create-team (with-meta params mdata)) (st/emit! (dd/create-team (with-meta params mdata))
(ptk/event ::ev/event {::ev/name "create-team-and-invite-later" (ptk/data-event ::ev/event
::ev/origin "onboarding" {::ev/name "onboarding-step"
:name name :label "team:create-team-and-invite-later"
:step 2}))))) :team-name name
:step 7})
(ptk/data-event ::ev/event
{::ev/name "onboarding-finish"})))))
;; The SUBMIT branch creates the team with the invitations
on-invite-now on-invite-now
(mf/use-fn (mf/use-fn
(fn [form] (fn [{:keys [name] :as params}]
(let [mdata {:on-success (partial on-success form) (let [mdata {:on-success on-success
:on-error (partial on-error form)} :on-error on-error}]
params (:clean-data @form)
emails (:emails params)]
(st/emit! (if (> (count emails) 0) (st/emit! (dd/create-team-with-invitations (with-meta params mdata))
;; If the user is only inviting to itself we don't call to create-team-with-invitations (ptk/data-event ::ev/event
(dd/create-team-with-invitations (with-meta params mdata)) {::ev/name "onboarding-step"
(dd/create-team (with-meta {:name name} mdata))) :label "team:create-team-and-invite"
(ptk/event ::ev/event {::ev/name "create-team-and-send-invitations" :invites (count emails)
::ev/origin "onboarding" :team-name name
:invites (count emails) :role (:role params)
:role (:role params) :step 7})
:name name (ptk/data-event ::ev/event
:step 2}))))) {::ev/name "onboarding-finish"})))))
on-submit on-submit
(mf/use-fn (mf/use-fn
@ -213,55 +133,146 @@
(let [params (:clean-data @form) (let [params (:clean-data @form)
emails (:emails params)] emails (:emails params)]
(if (> (count emails) 0) (if (> (count emails) 0)
(on-invite-now form) (on-invite-now params)
(on-invite-later form)) (on-invite-later params)))))]
(modal/hide!))))
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")]
[:div {:class (stl/css-case :modal-overlay true [:*
:onboarding-a-b-test onboarding-a-b-test?)} [:div {:class (stl/css :modal-right-invitations)}
[:div.animated.fadeIn {:class (stl/css :modal-container)} [:h2 {:class (stl/css :modal-subtitle)} (tr "onboarding.choice.team-up.invite-members")]
[:& team-modal-left] [:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
[:& fm/form {:form form
:class (stl/css :modal-form-invitations)
:on-submit on-submit}
[:div {:class (stl/css :role-select)}
[:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:div {:class (stl/css :separator)}] [:div {:class (stl/css :invitation-row)}
[:div {:class (stl/css :modal-right-invitations)} [:& fm/multi-input {:type "email"
[:h2 {:class (stl/css :modal-subtitle)} (tr "onboarding.choice.team-up.invite-members")] :name :emails
[:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")] :auto-focus? true
:trim true
:valid-item-fn us/parse-email
:caution-item-fn #{}
:label (tr "modals.invite-member.emails")
:on-submit on-submit}]]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :back-button)
:on-click on-back}
(tr "labels.back")]
[:> fm/submit-button*
{:class (stl/css :accept-button)
:label (if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-invite")
(tr "onboarding.choice.team-up.create-team-without-invite"))}]]
[:div {:class (stl/css :modal-hint)}
"(" (tr "onboarding.choice.team-up.create-team-and-send-invites-description") ")"]]]
[:div {:class (stl/css :paginator)} "2/2"]]))
(mf/defc team-form-step-1
{::mf/props :obj
::mf/private true}
[{:keys [on-submit]}]
(let [validators (mf/with-memo []
[(fm/validate-not-empty :name (tr "auth.name.not-all-space"))
(fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))])
form (fm/use-form
:spec ::team-form
:initial {}
:validators validators)
on-submit*
(mf/use-fn
(fn [form]
(let [name (dm/get-in @form [:clean-data :name])]
(st/emit! (ptk/data-event ::ev/event
{::ev/name "onboarding-step"
:label "team:choice-team-name"
:step 7}))
(on-submit name))))
on-skip
(mf/use-fn
(fn []
(st/emit! (du/update-profile-props {:onboarding-viewed true})
(ptk/data-event ::ev/event
{::ev/name "onboarding-step"
:label "team:skip-team-creation"
:step 7})
(ptk/data-event ::ev/event
{::ev/name "onboarding-finish"}))))]
[:*
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :first-block)}
[:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form [:& fm/form {:form form
:class (stl/css :modal-form-invitations) :class (stl/css :modal-form)
:on-submit on-submit} :on-submit on-submit*}
[:div {:class (stl/css :role-select)}
[:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:div {:class (stl/css :invitation-row)} [:& fm/input {:type "text"
[:& fm/multi-input {:type "email" :class (stl/css :team-name-input)
:name :emails :name :name
:auto-focus? true :placeholder "Team name"
:trim true :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
:valid-item-fn us/parse-email
:caution-item-fn #{}
:label (tr "modals.invite-member.emails")
:on-submit on-submit}]]
[:div {:class (stl/css :action-buttons)} [:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :back-button)
: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* [:> fm/submit-button*
{:class (stl/css :accept-button) {:class (stl/css :accept-button)
:label (if (> (count emails) 0) :label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
(tr "onboarding.choice.team-up.create-team-and-invite") [:div {:class (stl/css :second-block)}
(tr "onboarding.choice.team-up.create-team-without-invite"))}]] [:h2 {:class (stl/css :modal-subtitle)}
[:div {:class (stl/css :modal-hint)} (tr "onboarding.choice.team-up.start-without-a-team")]
(dmc/str "(" (tr "onboarding.choice.team-up.create-team-and-send-invites-description") ")")]]] [: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")]]]]
[:div {:class (stl/css :paginator)} "1/2"]]))
(s/def ::name ::us/not-empty-string)
(s/def ::team-form
(s/keys :req-un [::name]))
(mf/defc onboarding-team-modal
{::mf/props :obj}
[]
(let [name* (mf/use-state nil)
name (deref name*)
on-submit
(mf/use-fn
(fn [tname]
(swap! name* (constantly tname))))
[:div {:class (stl/css :paginator)} "2/2"]]])) on-back
(mf/use-fn
(fn []
(swap! name* (constantly nil))))
onboarding-a-b-test?
(cf/external-feature-flag "signup-background" "test")]
[:div {:class (stl/css-case
:modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:& left-sidebar]
[:div {:class (stl/css :separator)}]
(if name
[:& team-form-step-2 {:name name :on-back on-back}]
[:& team-form-step-1 {:on-submit on-submit}])]]))

View file

@ -160,6 +160,7 @@
.custom-input-token { .custom-input-token {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
margin: 0; margin: 0;
flex-grow: 1; flex-grow: 1;
&:focus { &:focus {

View file

@ -134,6 +134,8 @@
page-id (:id page) page-id (:id page)
file-id (:id file) file-id (:id file)
frame-id (:id frame) frame-id (:id frame)
vsize (-> (mf/deref refs/viewer-local)
:viewport-size)
tpos-ref (mf/with-memo [page-id] tpos-ref (mf/with-memo [page-id]
(-> (l/in [:pages page-id :options :comment-threads-position]) (-> (l/in [:pages page-id :options :comment-threads-position])
@ -216,6 +218,7 @@
[:& cmt/thread-comments [:& cmt/thread-comments
{:thread thread {:thread thread
:position-modifier modifier1 :position-modifier modifier1
:viewport {:offset-x 0 :offset-y 0 :width (:width vsize) :height (:height vsize)}
:users users :users users
:zoom zoom}]) :zoom zoom}])

View file

@ -92,6 +92,7 @@
.suffix-input { .suffix-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
grid-column: span 3; grid-column: span 3;
} }

View file

@ -63,6 +63,7 @@
.input-text { .input-text {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
color: var(--input-foreground-color-active); color: var(--input-foreground-color-active);
padding-left: $s-8; padding-left: $s-8;
margin: 0; margin: 0;

View file

@ -17,6 +17,7 @@
@include flexRow; @include flexRow;
.input-wrapper { .input-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-84; width: $s-84;
display: flex; display: flex;
align-items: baseline; align-items: baseline;
@ -26,6 +27,7 @@
@include flexRow; @include flexRow;
.input-wrapper { .input-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-84; width: $s-84;
&.hex { &.hex {
width: $s-172; width: $s-172;

View file

@ -36,6 +36,7 @@
.input-wrapper { .input-wrapper {
@extend .input-with-label; @extend .input-with-label;
@include bodySmallTypography;
label { label {
text-transform: none; text-transform: none;
} }

View file

@ -49,6 +49,7 @@
} }
.input-wrapper { .input-wrapper {
@extend .input-with-label; @extend .input-with-label;
@include bodySmallTypography;
margin-bottom: $s-8; margin-bottom: $s-8;
} }
.action-buttons { .action-buttons {

View file

@ -59,6 +59,7 @@
:ref dref :ref dref
:on-click on-select-shape :on-click on-select-shape
:on-context-menu on-context-menu :on-context-menu on-context-menu
:data-testid "layer-row"
:class (stl/css-case :class (stl/css-case
:layer-row true :layer-row true
:highlight highlighted? :highlight highlighted?

View file

@ -100,6 +100,7 @@
.second-row { .second-row {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-92; width: $s-92;
.label { .label {
padding-left: $s-8; padding-left: $s-8;

View file

@ -92,6 +92,7 @@
.suffix-input { .suffix-input {
grid-column: span 3; grid-column: span 3;
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
} }
.export-btn { .export-btn {

View file

@ -77,6 +77,7 @@
border-radius: 0 $br-8 $br-8 0; border-radius: 0 $br-8 $br-8 0;
.numeric-input { .numeric-input {
@extend .input-base; @extend .input-base;
@include bodySmallTypography;
} }
} }
.editable-select-wrapper { .editable-select-wrapper {
@ -93,6 +94,7 @@
border: $s-1 solid var(--input-border-color); border: $s-1 solid var(--input-border-color);
.numeric-input { .numeric-input {
@extend .input-base; @extend .input-base;
@include bodySmallTypography;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
@ -196,6 +198,7 @@
} }
.height { .height {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon-text { .icon-text {
padding-top: $s-1; padding-top: $s-1;
@ -204,6 +207,7 @@
.gutter, .gutter,
.margin { .margin {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon { .icon {
&.rotated svg { &.rotated svg {

View file

@ -33,6 +33,7 @@
.area-input { .area-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: 100%; width: 100%;
padding: $s-8; padding: $s-8;
} }
@ -51,6 +52,7 @@
.coord-input { .coord-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
border-radius: 0 $br-8 $br-8 0; border-radius: 0 $br-8 $br-8 0;
border-left: $s-1 solid var(--panel-background-color); border-left: $s-1 solid var(--panel-background-color);
} }

View file

@ -143,6 +143,7 @@
} }
.input-element-wrapper { .input-element-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
grid-area: content; grid-area: content;
} }
.buttons-wrapper { .buttons-wrapper {
@ -319,6 +320,7 @@
.flow-input { .flow-input {
@extend .input-base; @extend .input-base;
@include bodySmallTypography;
background-color: transparent; background-color: transparent;
height: $s-28; height: $s-28;
} }

View file

@ -19,6 +19,7 @@
} }
.input { .input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-60; width: $s-60;
} }
.actions { .actions {

View file

@ -84,6 +84,7 @@
gap: $s-4; gap: $s-4;
.column-gap { .column-gap {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;
@ -91,6 +92,7 @@
} }
.row-gap { .row-gap {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;
@ -113,6 +115,7 @@
.padding-simple { .padding-simple {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
max-width: $s-108; max-width: $s-108;
} }
} }
@ -124,6 +127,7 @@
.padding-multiple { .padding-multiple {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
max-width: $s-108; max-width: $s-108;
} }
} }
@ -239,6 +243,7 @@
.track-info-value { .track-info-value {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
border-radius: 0; border-radius: 0;
border-right: $s-1 solid var(--panel-background-color); border-right: $s-1 solid var(--panel-background-color);
} }

View file

@ -58,6 +58,7 @@
.z-index-wrapper { .z-index-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-60; width: $s-60;
} }
@ -94,6 +95,7 @@
.vertical-margin, .vertical-margin,
.horizontal-margin { .horizontal-margin {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
} }
} }
@ -109,6 +111,7 @@
.left-margin, .left-margin,
.right-margin { .right-margin {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
} }
@ -127,6 +130,7 @@
.layout-item-max-w, .layout-item-max-w,
.layout-item-max-h { .layout-item-max-h {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon-text { .icon-text {
justify-content: flex-start; justify-content: flex-start;

View file

@ -9,6 +9,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.logic.shapes :as cls]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.common.types.shape.radius :as ctsr] [app.common.types.shape.radius :as ctsr]
[app.main.constants :refer [size-presets]] [app.main.constants :refer [size-presets]]
@ -325,16 +326,15 @@
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/checked?) (let [value (-> event dom/get-target dom/checked?)
undo-id (js/Symbol)] undo-id (js/Symbol)]
(do (st/emit! (dwu/start-undo-transaction undo-id)
(st/emit! (dwu/start-undo-transaction undo-id) (dwsh/update-shapes ids (fn [shape] (cls/change-show-in-viewer shape (not value)))))
(dwsh/update-shapes ids (fn [shape] (assoc shape :hide-in-viewer (not value)))))
(when-not value (when-not value
;; when a frame is no longer shown in view mode, cannot have ;; when a frame is no longer shown in view mode, cannot have
;; interactions that navigate to it. ;; interactions that navigate to it.
(apply st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids))) (apply st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids)))
(st/emit! (dwu/commit-undo-transaction undo-id))))))] (st/emit! (dwu/commit-undo-transaction undo-id)))))]
(mf/use-layout-effect (mf/use-layout-effect
(mf/deps radius-mode @radius-multi?) (mf/deps radius-mode @radius-multi?)

View file

@ -114,6 +114,7 @@
.height, .height,
.width { .width {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon-text { .icon-text {
padding-top: $s-1; padding-top: $s-1;
@ -145,6 +146,7 @@
.x-position, .x-position,
.y-position { .y-position {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon-text { .icon-text {
padding-top: $s-1; padding-top: $s-1;
@ -163,6 +165,7 @@
.rotation { .rotation {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
.icon-text { .icon-text {
padding-top: $s-1; padding-top: $s-1;
@ -181,6 +184,7 @@
.radius-1 { .radius-1 {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-108; width: $s-108;
} }
@ -190,6 +194,7 @@
gap: $s-4; gap: $s-4;
.small-input { .small-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-52; width: $s-52;
} }
} }

View file

@ -114,6 +114,7 @@
.spread-input, .spread-input,
.offset-y-input { .offset-y-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-60; width: $s-60;
min-width: $s-60; min-width: $s-60;
align-items: baseline; align-items: baseline;

View file

@ -37,6 +37,7 @@
.attr-input { .attr-input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-124; width: $s-124;
} }

View file

@ -308,6 +308,7 @@
.line-height, .line-height,
.letter-spacing { .letter-spacing {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
.icon { .icon {
@include flexCenter; @include flexCenter;
width: $s-28; width: $s-28;
@ -339,6 +340,7 @@
padding: $s-8; padding: $s-8;
.numeric-input { .numeric-input {
@extend .input-base; @extend .input-base;
@include bodySmallTypography;
padding: 0; padding: 0;
} }
} }

View file

@ -41,6 +41,7 @@
.color-name-wrapper { .color-name-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
flex-grow: 1; flex-grow: 1;
width: 100%; width: 100%;
min-width: 0; min-width: 0;
@ -166,6 +167,7 @@
.opacity-element-wrapper { .opacity-element-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-60; width: $s-60;
border-radius: 0 $br-8 $br-8 0; border-radius: 0 $br-8 $br-8 0;
.opacity-input { .opacity-input {

View file

@ -12,6 +12,7 @@
@include flexRow; @include flexRow;
.stroke-width-input-element { .stroke-width-input-element {
@extend .input-element; @extend .input-element;
@include bodySmallTypography;
width: $s-60; width: $s-60;
} }
.select-wrapper { .select-wrapper {

View file

@ -7,6 +7,7 @@
(ns app.util.forms (ns app.util.forms
(:refer-clojure :exclude [uuid]) (:refer-clojure :exclude [uuid])
(:require (:require
[app.common.data :as d]
[app.common.spec :as us] [app.common.spec :as us]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -69,11 +70,15 @@
(::s/problems (s/explain-data spec (:data state)))) (::s/problems (s/explain-data spec (:data state))))
errors (reduce interpret-problem {} problems) errors (reduce interpret-problem {} problems)
errors (reduce (fn [errors vf] errors (reduce (fn [errors vf]
(merge errors (vf errors (:data state)))) (merge errors (vf errors (:data state))))
errors errors
validators) validators)
errors (merge errors (:errors state))] errors (merge (:errors state) errors)
errors (d/without-nils errors)]
(assoc state (assoc state
:errors errors :errors errors

View file

@ -278,7 +278,6 @@
old-id (parser/get-id node) old-id (parser/get-id node)
interactions (->> (parser/parse-interactions node) interactions (->> (parser/parse-interactions node)
(mapv #(update % :destination resolve))) (mapv #(update % :destination resolve)))
data (-> (parser/parse-data type node) data (-> (parser/parse-data type node)
(resolve-data-ids type context) (resolve-data-ids type context)
(cond-> (some? old-id) (cond-> (some? old-id)

View file

@ -244,19 +244,22 @@
(first)) (first))
;; The nodes with the "frame-background" class can have some anidation depending on the strokes they have ;; The nodes with the "frame-background" class can have some anidation depending on the strokes they have
g-nodes (find-all-nodes node :g) g-nodes (find-all-nodes node :g)
defs-nodes (flatten (map #(find-all-nodes % :defs) g-nodes)) defs-nodes (flatten (map #(find-all-nodes % :defs) g-nodes))
gg-nodes (flatten (map #(find-all-nodes % :g) g-nodes)) gg-nodes (flatten (map #(find-all-nodes % :g) g-nodes))
;; The first g node contains the opacity for frames
main-g-node (first g-nodes)
rect-nodes (flatten [[(find-all-nodes node :rect)] rect-nodes (flatten [[(find-all-nodes node :rect)]
(map #(find-all-nodes % #{:rect :path}) defs-nodes) (map #(find-all-nodes % #{:rect :path}) defs-nodes)
(map #(find-all-nodes % #{:rect :path}) g-nodes) (map #(find-all-nodes % #{:rect :path}) g-nodes)
(map #(find-all-nodes % #{:rect :path}) gg-nodes)]) (map #(find-all-nodes % #{:rect :path}) gg-nodes)])
svg-node (d/seek #(= "frame-background" (get-in % [:attrs :class])) rect-nodes)] svg-node (d/seek #(= "frame-background" (get-in % [:attrs :class])) rect-nodes)]
(merge (merge
(add-attrs {} (:attrs frame-clip-rect-node)) (add-attrs {} (:attrs frame-clip-rect-node))
(add-attrs {} (:attrs svg-node)) (add-attrs {} (:attrs svg-node))
(add-attrs {} (:attrs main-g-node))
node-attrs)) node-attrs))
(= type :svg-raw) (= type :svg-raw)

View file

@ -36,11 +36,6 @@ msgstr "ترغب في التجربة فحسب؟"
msgid "auth.demo-warning" msgid "auth.demo-warning"
msgstr "هذه خدمة تجريبية ، لا تستخدمها للعمل الحقيقي ، سيتم مسح المشاريع بشكل دوري." msgstr "هذه خدمة تجريبية ، لا تستخدمها للعمل الحقيقي ، سيتم مسح المشاريع بشكل دوري."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "البريد الالكتروني"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "هل نسيت كلمة السر؟" msgstr "هل نسيت كلمة السر؟"
@ -136,10 +131,6 @@ msgstr "لا تملك حساب بعد؟"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "إنشاء حساب" msgstr "إنشاء حساب"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "إنه مجاني ، مفتوح المصدر"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "إنشاء حساب" msgstr "إنشاء حساب"

View file

@ -35,10 +35,6 @@ msgstr ""
"এটি একটি ডেমো সার্ভিস। প্রয়োজনীয় কোনো কাজে ব্যবহার করবেন না। কিছু সময় পর " "এটি একটি ডেমো সার্ভিস। প্রয়োজনীয় কোনো কাজে ব্যবহার করবেন না। কিছু সময় পর "
"প্রজেক্টগুলো মুছে ফেলা হবে।" "প্রজেক্টগুলো মুছে ফেলা হবে।"
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "ইমেইল"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "পাসওয়ার্ড ভুলে গেছেন?" msgstr "পাসওয়ার্ড ভুলে গেছেন?"

View file

@ -39,11 +39,6 @@ msgstr ""
"Aquest és un servei de PROVA. NO L'UTILITZEU en treballs reals, ja que els " "Aquest és un servei de PROVA. NO L'UTILITZEU en treballs reals, ja que els "
"projectes s'eliminaran periòdicament." "projectes s'eliminaran periòdicament."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Correu electrònic"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Heu oblidat la contrasenya?" msgstr "Heu oblidat la contrasenya?"
@ -139,10 +134,6 @@ msgstr "No teniu un compte?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Creeu un compte" msgstr "Creeu un compte"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "És gratuït, és de codi obert"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Crea un compte" msgstr "Crea un compte"
@ -154,12 +145,6 @@ msgstr "La solució de codi obert per a dissenyar i prototipar."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Condicions del servei" msgstr "Condicions del servei"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"En crear un compte nou, accepteu les condicions del servei i la política de "
"privadesa."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "S'ha enviat un correu de verificació a" msgstr "S'ha enviat un correu de verificació a"

View file

@ -39,11 +39,6 @@ msgstr ""
"Toto je DEMO služba, NEPOUŽÍVEJTE ji pro skutečnou práci, projekty budou " "Toto je DEMO služba, NEPOUŽÍVEJTE ji pro skutečnou práci, projekty budou "
"pravidelně mazány." "pravidelně mazány."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Zapomněli jste heslo?" msgstr "Zapomněli jste heslo?"
@ -151,10 +146,6 @@ msgstr "Ještě nemáte účet?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Vytvořit účet" msgstr "Vytvořit účet"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Je to zdarma, je to open source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Vytvořit účet" msgstr "Vytvořit účet"
@ -5120,4 +5111,4 @@ msgid "workspace.updates.update"
msgstr "Aktualizace" msgstr "Aktualizace"
msgid "workspace.viewport.click-to-close-path" msgid "workspace.viewport.click-to-close-path"
msgstr "Kliknutím zavřete cestu" msgstr "Kliknutím zavřete cestu"

View file

@ -39,10 +39,6 @@ msgstr ""
"Det her er en DEMO service, BRUG IKKE for rigtigt arbejde, projekterne vil " "Det her er en DEMO service, BRUG IKKE for rigtigt arbejde, projekterne vil "
"blive slettet periodevis." "blive slettet periodevis."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Glemt adgangskode?" msgstr "Glemt adgangskode?"
@ -135,10 +131,6 @@ msgstr "Ingen konto?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Opret en konto" msgstr "Opret en konto"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Det er gratis, det er Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Opret en konto" msgstr "Opret en konto"
@ -147,12 +139,6 @@ msgstr "Opret en konto"
msgid "auth.sidebar-tagline" msgid "auth.sidebar-tagline"
msgstr "Open-source løsningen for design og prototyping." msgstr "Open-source løsningen for design og prototyping."
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Når du opretter en ny konto, accepterer du vores servicevilkår og "
"fortrolighedspolitik."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Vi har sendt en bekræftelsesmail til" msgstr "Vi har sendt en bekræftelsesmail til"

View file

@ -39,11 +39,6 @@ msgstr ""
"Das ist eine DEMO-VERSION, verwenden Sie es NICHT zum Arbeiten, die Projekte " "Das ist eine DEMO-VERSION, verwenden Sie es NICHT zum Arbeiten, die Projekte "
"werden regelmäßig gelöscht." "werden regelmäßig gelöscht."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "E-Mail"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Passwort vergessen?" msgstr "Passwort vergessen?"
@ -176,10 +171,6 @@ msgstr "Noch kein Konto?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Konto erstellen" msgstr "Konto erstellen"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Kostenlos, es ist Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Konto erstellen" msgstr "Konto erstellen"

View file

@ -39,11 +39,6 @@ msgstr ""
"Αυτή είναι μια υπηρεσία DEMO, ΜΗ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ για πραγματική εργασία, τα " "Αυτή είναι μια υπηρεσία DEMO, ΜΗ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ για πραγματική εργασία, τα "
"έργα θα σβήνονται περιοδικά." "έργα θα σβήνονται περιοδικά."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Ξεχάσατε τον κωδικό;" msgstr "Ξεχάσατε τον κωδικό;"
@ -134,10 +129,6 @@ msgstr "Δεν έχετε λογαριασμό;"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Δημιουργία λογαριασμού" msgstr "Δημιουργία λογαριασμού"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Είναι δωρεάν, είναι Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Δημιουργία λογαριασμού" msgstr "Δημιουργία λογαριασμού"
@ -146,12 +137,6 @@ msgstr "Δημιουργία λογαριασμού"
msgid "auth.sidebar-tagline" msgid "auth.sidebar-tagline"
msgstr "Η λύση ανοιχτού κώδικα για σχεδιασμό και πρωτότυπο." msgstr "Η λύση ανοιχτού κώδικα για σχεδιασμό και πρωτότυπο."
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Δημιουργώντας έναν νέο λογαριασμό, αποδέχεστε τους όρους παροχής υπηρεσιών "
"και την πολιτική απορρήτου."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Εχουμε στείλει ενα mail επαλήθευσης " msgstr "Εχουμε στείλει ενα mail επαλήθευσης "

View file

@ -38,8 +38,8 @@ msgstr ""
"periodically wiped." "periodically wiped."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email" msgid "auth.work-email"
msgstr "Email" msgstr "Work email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
@ -55,7 +55,11 @@ msgstr "Log into my account"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.login-here" msgid "auth.login-here"
msgstr "Login here" msgstr "Login here."
#: src/app/main/ui/auth/register.cljs
msgid "auth.check-mail"
msgstr "Check your email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.login-submit" msgid "auth.login-submit"
@ -65,6 +69,14 @@ msgstr "Login"
msgid "auth.login-tagline" msgid "auth.login-tagline"
msgstr "Penpot is the free open-source design tool for Design and Code collaboration" msgstr "Penpot is the free open-source design tool for Design and Code collaboration"
#: src/app/main/ui/auth/login.cljs
msgid "auth.register-tagline"
msgstr "With a free Penpot account, you can create unlimited teams and collaborate with other designers and developers on as many projects as you like. "
#: src/app/main/ui/auth/login.cljs
msgid "auth.register-account-tagline"
msgstr "Let us know what we should call you on the dashboard and in emails."
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.login-with-github-submit" msgid "auth.login-with-github-submit"
msgstr "GitHub" msgstr "GitHub"
@ -156,14 +168,14 @@ msgstr "No account yet?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Create an account" msgstr "Create an account"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "It's free, it's Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Create an account" msgstr "Create an account"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-account-title"
msgstr "Your name"
#: src/app/main/ui/auth.cljs #: src/app/main/ui/auth.cljs
msgid "auth.sidebar-tagline" msgid "auth.sidebar-tagline"
msgstr "The open-source solution for design and prototyping." msgstr "The open-source solution for design and prototyping."
@ -178,10 +190,9 @@ msgstr ""
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
#, markdown #, markdown
msgid "auth.terms-privacy-agreement-md" msgid "auth.terms-and-privacy-agreement"
msgstr "" msgstr ""
"When creating a new account, you agree to our [terms of service](%s) and " "I agree to the [terms of service](%s) and [privacy policy](%s)."
"[privacy policy](%s)."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
@ -2382,24 +2393,52 @@ msgid "profile.recovery.go-to-login"
msgstr "Go to login" msgstr "Go to login"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "question.design-tool-more-experienced-with" msgid "questions.step1-title"
msgstr "Which is the design tool you have more experience with?" msgstr "Help us get to know you"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.11-30" msgid "questions.step1-subtitle"
msgstr "11-30" msgstr "Let us know a bit about you to help us make Penpot work for you. Your answers will help us prioritize new features and point you in the right direction to get started."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.2-10" msgid "questions.step1-question1"
msgstr "2-10" msgstr "What will you be using Penpot for?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.31-50" msgid "questions.use-work"
msgstr "31-50" msgstr "Work"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot" msgid "questions.use-education"
msgstr "A lot" msgstr "Education"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.use-personal"
msgstr "Personal"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step1-question2"
msgstr "What brings you to Penpot today?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.exploring"
msgstr "Just exploring"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.fit"
msgstr "Reviewing whether Penpot is a good fit for my team"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.alternative"
msgstr "Looking for an alternative to Figma, XD, etc"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.testing"
msgstr "Testing before self-hosting"
#: src/app/main/ui/onboarding/questions.cljs
msgid "question.design-tool-more-used"
msgstr "Which one of these tools do you use the most?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
@ -2409,148 +2448,182 @@ msgstr "Adobe XD"
msgid "questions.canva" msgid "questions.canva"
msgstr "Canva" msgstr "Canva"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.describe-your-experience-working-on"
msgstr "How would you best describe your experience working on..."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.designer"
msgstr "Designer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.developer"
msgstr "Developer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.discover-more-about-penpot"
msgstr "Discover more about Penpot"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.figma" msgid "questions.figma"
msgstr "Figma" msgstr "Figma"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.founder"
msgstr "Founder/VP"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.freelancer"
msgstr "I'm a freelancer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.get-the-code-from-my-team-project"
msgstr "Get the code from my team project "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.interface-design-visual-assets-design-systems"
msgstr "... interface design, visual assets, design systems, etc."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.invision" msgid "questions.invision"
msgstr "InVision" msgstr "InVision"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.leave-feedback-for-my-team-project" msgid "questions.sketch"
msgstr "Leave feedback for my team project" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started" msgid "questions.step3-title"
msgstr "Let's get started!" msgstr "Tell us about your job"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.manager" msgid "questions.step3.question1"
msgstr "Product or Project manager" msgstr "What kind of work do you do?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.marketing" msgid "questions.work-type.ux"
msgstr "Product or UX design"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.dev"
msgstr "Development"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.student"
msgstr "student"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.graphic"
msgstr "Graphic design"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.marketing"
msgstr "Marketing" msgstr "Marketing"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.product"
msgstr "Product Managment"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step3.question2"
msgstr "What's your role?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.team-leader"
msgstr "Team Leader"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.team-member"
msgstr "Team member"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.freelancer"
msgstr "Freelancer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.founder"
msgstr "CEO or Founder"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.director"
msgstr "Director"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.company-size"
msgstr "What's the size of your company?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.more-than-50" msgid "questions.more-than-50"
msgstr "More than 50" msgstr "More than 50"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.never-used-one" msgid "questions.31-50"
msgstr "None" msgstr "31-50"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.next" msgid "questions.11-30"
msgstr "Next" msgstr "11-30"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none" msgid "questions.2-10"
msgstr "None" msgstr "2-10"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.freelancer"
msgstr "Other (specify)" msgstr "I'm a freelancer"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.personal-project" msgid "questions.personal-project"
msgstr "Im working in a personal project" msgstr "Im working in a personal project"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step4-title"
msgstr "Where would you like to get started?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-ui"
msgstr "Design the UI/UX of an app"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-wireframing"
msgstr "Wireframing"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-prototyping"
msgstr "Prototyping"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-ds"
msgstr "Creating Desing Systems"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-code"
msgstr "Generating real code designs"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step5-title"
msgstr "How did you hear about Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.youtube"
msgstr "YouTube"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.event"
msgstr "Event"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.search"
msgstr "Search Engine (Google, Yahoo, Bing)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.social"
msgstr "Social Media (X, Linkedin, FB, etc)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.article"
msgstr "Article (Blog, Post, Newsletter)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started"
msgstr "Let's get started!"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.next"
msgstr "Next"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other"
msgstr "Other (specify)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other-short"
msgstr "Other"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.previous" msgid "questions.previous"
msgstr "Previous" msgstr "Previous"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.questions-how-are-you-planning-to-use-penpot"
msgstr "How are you planning to use Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role"
msgstr "What's your role?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.select-option" msgid "questions.select-option"
msgstr "Select option" msgstr "Select option"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.sketch"
msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "Some"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "Start" msgstr "Start"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start-to-work-on-my-project"
msgstr "Start to work on my project"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.student-teacher" msgid "questions.student-teacher"
msgstr "Student or teacher" msgstr "Student or teacher"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.team-size"
msgstr "What's the size of your team?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.test-penpot-to-see-if-its-a-fit-for-team"
msgstr "Test Penpot to see if it's a fit for team "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.try-out-before-using-penpot-on-premise"
msgstr "Try out before using Penpot on-premise"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.wireframes-user-journeys-flows-navigation-trees"
msgstr "... wireframes, user journeys & flows, navigation trees, etc."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-in-concept-ideas"
msgstr "Work in concept ideas"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.your-feedback-will-help-us"
msgstr ""
"Your feedback will help us understand what your habits and preferences are "
"so that we can keep making Penpot such a useful and enjoyable tool."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs, #: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
msgid "settings.detach" msgid "settings.detach"
msgstr "Detach" msgstr "Detach"
@ -2563,6 +2636,7 @@ msgstr "Mixed"
msgid "settings.select-this-color" msgid "settings.select-this-color"
msgstr "Select items using this style" msgstr "Select items using this style"
# SECTIONS # SECTIONS
msgid "shortcut-section.basics" msgid "shortcut-section.basics"
msgstr "Basics" msgstr "Basics"

View file

@ -39,9 +39,8 @@ msgstr ""
"Este es un servicio de DEMOSTRACIÓN. NO USAR para trabajo real, los " "Este es un servicio de DEMOSTRACIÓN. NO USAR para trabajo real, los "
"proyectos serán borrados periodicamente." "proyectos serán borrados periodicamente."
#: src/app/main/ui/auth/register.cljs, #: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs msgid "auth.work-email"
msgid "auth.email"
msgstr "Correo electrónico" msgstr "Correo electrónico"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
@ -58,7 +57,7 @@ msgstr "Entrar en mi cuenta"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.login-here" msgid "auth.login-here"
msgstr "Inicia sesión aquí" msgstr "Inicia sesión aquí."
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.login-submit" msgid "auth.login-submit"
@ -70,6 +69,14 @@ msgstr ""
"Penpot es la herramienta de diseño libre y open-source para la colaboración " "Penpot es la herramienta de diseño libre y open-source para la colaboración "
"entre Diseño y Código" "entre Diseño y Código"
#: src/app/main/ui/auth/login.cljs
msgid "auth.register-tagline"
msgstr "Con una cuenta gratuita de Penpot, puedes crear un número ilimitado de equipos y colaborar con otros diseñadores y desarrolladores en tantos proyectos como quieras."
#: src/app/main/ui/auth/login.cljs
msgid "auth.register-account-tagline"
msgstr "Cuéntanos cómo quieres que nos dirijamos a tí."
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.login-with-github-submit" msgid "auth.login-with-github-submit"
msgstr "GitHub" msgstr "GitHub"
@ -163,14 +170,14 @@ msgstr "¿No tienes una cuenta?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Crear una cuenta" msgstr "Crear una cuenta"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Es gratis, es Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Crear una cuenta" msgstr "Crear una cuenta"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-account-title"
msgstr "Tu nombre"
#: src/app/main/ui/auth.cljs #: src/app/main/ui/auth.cljs
msgid "auth.sidebar-tagline" msgid "auth.sidebar-tagline"
msgstr "La solución de código abierto para diseñar y prototipar." msgstr "La solución de código abierto para diseñar y prototipar."
@ -190,10 +197,20 @@ msgstr ""
"Al crear una nueva cuenta, aceptas nuestros [términos de servicio](%s) y " "Al crear una nueva cuenta, aceptas nuestros [términos de servicio](%s) y "
"[política de privacidad](%s)." "[política de privacidad](%s)."
#: src/app/main/ui/auth/register.cljs
#, markdown
msgid "auth.terms-and-privacy-agreement"
msgstr ""
"Yo acepto los [términos de servicio](%s) y la [política de privacidad](%s)."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Hemos enviado un email de verificación a" msgstr "Hemos enviado un email de verificación a"
#: src/app/main/ui/auth/register.cljs
msgid "auth.check-mail"
msgstr "Comprueba tu correo"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "branding-illustrations-marketing-pieces" msgid "branding-illustrations-marketing-pieces"
msgstr "diseño de marca, ilustraciones, piezas de marketing..." msgstr "diseño de marca, ilustraciones, piezas de marketing..."
@ -2455,25 +2472,84 @@ msgstr "Penpot"
msgid "profile.recovery.go-to-login" msgid "profile.recovery.go-to-login"
msgstr "Ir al login" msgstr "Ir al login"
#: src/app/main/ui/onboarding/questions.cljs
msgid "question.design-tool-more-experienced-with"
msgstr "¿Cuál es la herramienta de diseño con la que tienes más experiencia?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.11-30" msgid "questions.step1-title"
msgstr "11-30" msgstr "Ayúdanos a conocerte"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.2-10" msgid "questions.step1-subtitle"
msgstr "2-10" msgstr "Cuéntanos un poco sobre tí para ayudarnos a que Penpot se adapte mejor a tí. Tus respuestas nos ayudarán a priorizar nuevas funcionalidades y a saber cómo podemos acompañarte mejor."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.31-50" msgid "questions.step1-question1"
msgstr "31-50" msgstr "¿Para qué utilizarás Penpot?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot" msgid "questions.use-work"
msgstr "Mucha" msgstr "Trabajo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.use-education"
msgstr "Educación"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.use-personal"
msgstr "Personal"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step1-question2"
msgstr "¿Qué te ha traído a Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.exploring"
msgstr "Estoy echando un vistazo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.fit"
msgstr "Averiguar si Penpot es una buena opción para mi equipo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.alternative"
msgstr "Buscar una alternativa a Figma, XD, etc."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.reasons.testing"
msgstr "Probar antes de self-hosting"
#: src/app/main/ui/onboarding/questions.cljs
msgid "question.design-tool-more-used"
msgstr "¿Cuál de estas herramientas utilizas más?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
@ -2483,148 +2559,182 @@ msgstr "Adobe XD"
msgid "questions.canva" msgid "questions.canva"
msgstr "Canva" msgstr "Canva"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.describe-your-experience-working-on"
msgstr "Cuánta experiencia dirías que tienes trabajando con..."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.designer"
msgstr "Diseño"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.developer"
msgstr "Desarrollo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.discover-more-about-penpot"
msgstr "Conocer Penpot mejor"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.figma" msgid "questions.figma"
msgstr "Figma" msgstr "Figma"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.founder"
msgstr "Dirección"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.freelancer"
msgstr "Soy freelancer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.get-the-code-from-my-team-project"
msgstr "Obtener código de un proyecto"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.interface-design-visual-assets-design-systems"
msgstr "diseño de interfaz, visual, sistemas de diseño..."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.invision" msgid "questions.invision"
msgstr "InVision" msgstr "InVision"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.leave-feedback-for-my-team-project" msgid "questions.sketch"
msgstr "Dejar comentarios en un proyecto" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started" msgid "questions.step3-title"
msgstr "¡Empecemos!" msgstr "Háblanos de tu trabajo"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.manager" msgid "questions.step3.question1"
msgstr "Gestión de producto o proyecto" msgstr "¿Qué tipo de trabajo haces?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.marketing" msgid "questions.work-type.ux"
msgstr "Diseño de Producto o UX"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.dev"
msgstr "Desarrollo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.student"
msgstr "Estudiante"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.graphic"
msgstr "Diseño gráfico"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.marketing"
msgstr "Marketing" msgstr "Marketing"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-type.product"
msgstr "Product Managment"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step3.question2"
msgstr "¿Cuál es tu puesto?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.team-leader"
msgstr "Líder de equipo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.team-member"
msgstr "Miembro de equipo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.freelancer"
msgstr "Autónomo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.founder"
msgstr "CEO o Fundador"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role.director"
msgstr "Director"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.company-size"
msgstr "¿Cuál es el tamaño de tu empresa?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.more-than-50" msgid "questions.more-than-50"
msgstr "Más de 50" msgstr "Más de 50"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.never-used-one" msgid "questions.31-50"
msgstr "Ninguna" msgstr "31-50"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.next" msgid "questions.11-30"
msgstr "Siguiente" msgstr "11-30"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none" msgid "questions.2-10"
msgstr "Ninguna" msgstr "2-10"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.freelancer"
msgstr "Otra (especifica)" msgstr "Soy autónomo"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.personal-project" msgid "questions.personal-project"
msgstr "Estoy trabajando en un proyecto personal" msgstr "Estoy trabajando en un proyecto personal"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step4-title"
msgstr "¿Por dónde te apetecería empezar?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-ui"
msgstr "Diseñando el UX/UI de una aplicación"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-wireframing"
msgstr "Wireframing"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-prototyping"
msgstr "Prototipado"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-ds"
msgstr "Creando sistemas de diseño"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.starting-code"
msgstr "Generando código a partir de diseños"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.step5-title"
msgstr "¿Cómo nos has descubierto?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.youtube"
msgstr "YouTube"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.event"
msgstr "Evento"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.search"
msgstr "Buscador (Google, Yahoo, Bing)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.social"
msgstr "Redes sociales (X, LinkedIn, FB, ect)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.referer.article"
msgstr "Artículo (Blog, Post, Newsletter)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started"
msgstr "¡Empecemos!"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.next"
msgstr "Siguiente"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other"
msgstr "Otra (especifica)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other-short"
msgstr "Otra"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.previous" msgid "questions.previous"
msgstr "Anterior" msgstr "Anterior"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.questions-how-are-you-planning-to-use-penpot"
msgstr "¿Qué uso piensas darle a Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role"
msgstr "¿Cuál es tu rol?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.select-option" msgid "questions.select-option"
msgstr "Selecciona una opción" msgstr "Selecciona una opción"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.sketch"
msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "Alguna"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "Comenzar" msgstr "Comenzar"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start-to-work-on-my-project"
msgstr "Comenzar a trabajar en mi proyecto"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.student-teacher" msgid "questions.student-teacher"
msgstr "Estudiante o profesorado" msgstr "Estudiante o profesorado"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.team-size"
msgstr "¿De qué tamaño es tu equipo?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.test-penpot-to-see-if-its-a-fit-for-team"
msgstr "Valorar si Penpot es adecuado para mi equipo"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.try-out-before-using-penpot-on-premise"
msgstr "Probar Penpot antes de usarlo en una instalación propia"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.wireframes-user-journeys-flows-navigation-trees"
msgstr "prototipos, user journeys, flujos, árboles de navegación..."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-in-concept-ideas"
msgstr "Conceptualizar ideas"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.your-feedback-will-help-us"
msgstr ""
"Tus respuestas nos ayudarán a entender tus hábitos y preferencias, lo que "
"nos ayudará a continuar mejorando Penpot"
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs, #: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
msgid "settings.detach" msgid "settings.detach"
msgstr "Desacoplar" msgstr "Desacoplar"

View file

@ -39,11 +39,6 @@ msgstr ""
"Hau PROBAK EGITEKO zerbitzua da. EZ ERABILI benetako lana egiteko, hemengo " "Hau PROBAK EGITEKO zerbitzua da. EZ ERABILI benetako lana egiteko, hemengo "
"proiektuak noizean behin ezabatu egingo dira." "proiektuak noizean behin ezabatu egingo dira."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Posta elektronikoa"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Pasahitza ahaztu duzu?" msgstr "Pasahitza ahaztu duzu?"
@ -139,10 +134,6 @@ msgstr "Ez duzu konturik?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Sortu kontua" msgstr "Sortu kontua"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Doakoa da, Kode Irekia da"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Sortu kontua" msgstr "Sortu kontua"
@ -154,12 +145,6 @@ msgstr "Diseinuak eta prototipoak egiteko kode irekiko soluzioa."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Zerbitzuaren erabilpen-baldintzak" msgstr "Zerbitzuaren erabilpen-baldintzak"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Kontu berri bat sortzean, gure erabilpen-baldintzak eta pribatutasun "
"politika onartzen dituzu."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Egiaztapen mezu bat bidali dugu helbide honetara" msgstr "Egiaztapen mezu bat bidali dugu helbide honetara"

View file

@ -39,11 +39,6 @@ msgstr ""
"این یک سرویس آزمایشی است، برای کار واقعی استفاده نکنید، پروژه‌ها به صورت " "این یک سرویس آزمایشی است، برای کار واقعی استفاده نکنید، پروژه‌ها به صورت "
"دوره‌ای پاک می‌شوند." "دوره‌ای پاک می‌شوند."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "ایمیل"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "کلمه‌عبور را فراموش کرده‌اید؟" msgstr "کلمه‌عبور را فراموش کرده‌اید؟"
@ -139,10 +134,6 @@ msgstr "هنوز حسابی ندارید؟"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "ایجاد حساب‌کاربری" msgstr "ایجاد حساب‌کاربری"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "رایگان است، منبع‌باز است"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "ایجاد حساب" msgstr "ایجاد حساب"
@ -154,12 +145,6 @@ msgstr "راه حل منبع-باز برای طراحی و نمونه‌سازی
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "شرایط استفاده از خدمات" msgstr "شرایط استفاده از خدمات"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"هنگام ایجاد یک حساب‌کاربری جدید، با شرایط خدمات و سیاست حفظ حریم‌خصوصی ما "
"موافقت می‌کنید."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "ما یک ایمیل تأیید ارسال کردیم به" msgstr "ما یک ایمیل تأیید ارسال کردیم به"

View file

@ -39,10 +39,6 @@ msgstr ""
"Tämä on DEMO versio, ÄLÄ KÄYTÄ oikeaan työhön, projektit tullaan määräajoin " "Tämä on DEMO versio, ÄLÄ KÄYTÄ oikeaan työhön, projektit tullaan määräajoin "
"poistamaan." "poistamaan."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Sähköposti"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Unohditko salasanasi?" msgstr "Unohditko salasanasi?"
@ -138,11 +134,6 @@ msgstr "Ei käyttäjää?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Luo uusi käyttäjä" msgstr "Luo uusi käyttäjä"
#: src/app/main/ui/auth/register.cljs
#, fuzzy
msgid "auth.register-subtitle"
msgstr "Se on ilmainen, sekä avointa lähdekoodia"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Luo uusi käyttäjä" msgstr "Luo uusi käyttäjä"
@ -154,10 +145,6 @@ msgstr "Avoimen lähdekoodin ratkaisu suunnitteluun ja prototyyppien valmistukse
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Käyttöehdot" msgstr "Käyttöehdot"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr "Kun luot uuden käyttäjän, hyväksyt käyttöehdot ja tietosuojaselosteen."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Lähetimme vahvistussähköpostin osoitteeseen" msgstr "Lähetimme vahvistussähköpostin osoitteeseen"

View file

@ -39,11 +39,6 @@ msgstr ""
"Hetta er ein ROYNDAR tænasta, IKKI BRÚKA til veruligt arbeiði, " "Hetta er ein ROYNDAR tænasta, IKKI BRÚKA til veruligt arbeiði, "
"verkætlanirnar verða slettaðar regluliga." "verkætlanirnar verða slettaðar regluliga."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Teldupostur"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Gloymt loyniorðið?" msgstr "Gloymt loyniorðið?"
@ -137,10 +132,6 @@ msgstr "Onga konto enn?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Stovna konto" msgstr "Stovna konto"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Tað er ókeypis, tað Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Stovna eina konto" msgstr "Stovna eina konto"
@ -148,12 +139,6 @@ msgstr "Stovna eina konto"
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Treytir" msgstr "Treytir"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Tá ið tú gert eina nýggja kontu, játtar tú tænastu- og privatlívs-treytir "
"okkara."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Vit hava sent ein váttanar teldupost til" msgstr "Vit hava sent ein váttanar teldupost til"

View file

@ -39,11 +39,6 @@ msgstr ""
"Il sagit dun service de DÉMONSTRATION, NE L'UTILISEZ PAS pour du vrai " "Il sagit dun service de DÉMONSTRATION, NE L'UTILISEZ PAS pour du vrai "
"travail, les projets seront périodiquement supprimés." "travail, les projets seront périodiquement supprimés."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Adresse email"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Mot de passe oublié?" msgstr "Mot de passe oublié?"
@ -151,10 +146,6 @@ msgstr "Pas encore de compte?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Créer un compte" msgstr "Créer un compte"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Cest gratuit, cest Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Créer un compte" msgstr "Créer un compte"
@ -166,12 +157,6 @@ msgstr "La solution Open Source pour la conception et le prototypage."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Conditions générales d'utilisation" msgstr "Conditions générales d'utilisation"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"En créant un compte, vous acceptez nos conditions générales d'utilisation "
"et notre politique de confidentialité."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Nous avons envoyé un e-mail de vérification à" msgstr "Nous avons envoyé un e-mail de vérification à"

View file

@ -39,11 +39,6 @@ msgstr ""
"Este é un servizo de DEMOSTRACIÓN. NON O UTILICES para traballos reais, os " "Este é un servizo de DEMOSTRACIÓN. NON O UTILICES para traballos reais, os "
"proxectos eliminanse periódicamente." "proxectos eliminanse periódicamente."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Correo electrónico"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Esqueciches o teu contrasinal?" msgstr "Esqueciches o teu contrasinal?"
@ -139,10 +134,6 @@ msgstr "Ainda non tes unha conta?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Crea unha conta" msgstr "Crea unha conta"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "É libre, é Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Crea unha conta" msgstr "Crea unha conta"
@ -154,12 +145,6 @@ msgstr "A solución de código aberto para deseñar e crear prototipos."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Condicións de servizo" msgstr "Condicións de servizo"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Ao crear unha nova conta, aceptas as nosas condicións de servizo e a "
"política de privacidade."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Enviamos un correo electrónico de verificación a" msgstr "Enviamos un correo electrónico de verificación a"

View file

@ -38,11 +38,6 @@ msgid "auth.demo-warning"
msgstr "" msgstr ""
"זה שירות ניסיוני, לא להשתמש בו לעבודה אמתית, המיזמים יימחקו מדי פעם בפעם." "זה שירות ניסיוני, לא להשתמש בו לעבודה אמתית, המיזמים יימחקו מדי פעם בפעם."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "דוא״ל"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "שכחת סיסמה?" msgstr "שכחת סיסמה?"
@ -170,10 +165,6 @@ msgstr "אין לך חשבון עדיין?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "יצירת חשבון" msgstr "יצירת חשבון"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "זה חינם, בקוד פתוח"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "יצירת חשבון" msgstr "יצירת חשבון"
@ -2447,10 +2438,6 @@ msgstr "2-10"
msgid "questions.31-50" msgid "questions.31-50"
msgstr "31-50" msgstr "31-50"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot"
msgstr "הרבה מהם"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
msgstr "Adobe XD" msgstr "Adobe XD"
@ -2459,22 +2446,6 @@ msgstr "Adobe XD"
msgid "questions.canva" msgid "questions.canva"
msgstr "Canva" msgstr "Canva"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.describe-your-experience-working-on"
msgstr "מה יתאר הכי טוב את אופן השימוש שלך…"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.designer"
msgstr "עיצוב"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.developer"
msgstr "פיתוח"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.discover-more-about-penpot"
msgstr "היכרות מעמיקה יותר עם Penpot"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.figma" msgid "questions.figma"
msgstr "Figma" msgstr "Figma"
@ -2507,14 +2478,6 @@ msgstr "להשאיר משוב למיזם הצוותי שלי"
msgid "questions.lets-get-started" msgid "questions.lets-get-started"
msgstr "מתחילים!" msgstr "מתחילים!"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.manager"
msgstr "ניהול מוצר או מיזם"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.marketing"
msgstr "שיווק"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.more-than-50" msgid "questions.more-than-50"
msgstr "גדול מ־50" msgstr "גדול מ־50"
@ -2527,10 +2490,6 @@ msgstr "אין"
msgid "questions.next" msgid "questions.next"
msgstr "הבאה" msgstr "הבאה"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none"
msgstr "כלום"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.other"
msgstr "אחר (נא לפרט)" msgstr "אחר (נא לפרט)"
@ -2543,14 +2502,6 @@ msgstr "זאת עבודה על מיזם פרטי"
msgid "questions.previous" msgid "questions.previous"
msgstr "הקודמת" msgstr "הקודמת"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.questions-how-are-you-planning-to-use-penpot"
msgstr "מהן התוכניות שלך בנוגע לשימוש ב־Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role"
msgstr "מה התפקיד שלך?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.select-option" msgid "questions.select-option"
msgstr "בחירת אפשרות" msgstr "בחירת אפשרות"
@ -2559,10 +2510,6 @@ msgstr "בחירת אפשרות"
msgid "questions.sketch" msgid "questions.sketch"
msgstr "Sketch" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "חלק מהם"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "התחלה" msgstr "התחלה"

View file

@ -38,11 +38,6 @@ msgstr ""
"Ovo je DEMO usluga. NEMOJ KORISTITI za pravi rad. Projekti će se povremeno " "Ovo je DEMO usluga. NEMOJ KORISTITI za pravi rad. Projekti će se povremeno "
"brisati." "brisati."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "E-mail"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Zaboravljena lozinka?" msgstr "Zaboravljena lozinka?"
@ -138,10 +133,6 @@ msgstr "Još nemaš račun?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Stvori račun" msgstr "Stvori račun"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Besplatno je, Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Stvori račun" msgstr "Stvori račun"
@ -153,12 +144,6 @@ msgstr "Open Source rješenje za dizajn i izradu prototipova."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Uvjeti pružanja usluge" msgstr "Uvjeti pružanja usluge"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Kada kreiraš novi račun, slažeš se s našim uvjetima pružanja usluge i "
"pravilima privatnosti."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Poslali smo e-mail za potvrdu na" msgstr "Poslali smo e-mail za potvrdu na"

View file

@ -39,11 +39,6 @@ msgstr ""
"Ini layanan DEMO, JANGAN GUNAKAN untuk pekerjaan nyata, proyek-proyek ini " "Ini layanan DEMO, JANGAN GUNAKAN untuk pekerjaan nyata, proyek-proyek ini "
"akan di hapus secara berkala." "akan di hapus secara berkala."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Surel"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Lupa kata sandi?" msgstr "Lupa kata sandi?"
@ -164,10 +159,6 @@ msgstr "Belum punya akun?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Buat akun baru" msgstr "Buat akun baru"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Gratis dan Sumber Terbuka"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Buat akun baru" msgstr "Buat akun baru"
@ -2428,10 +2419,6 @@ msgstr "210"
msgid "questions.31-50" msgid "questions.31-50"
msgstr "3150" msgstr "3150"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot"
msgstr "Banyak"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
msgstr "Adobe XD" msgstr "Adobe XD"
@ -2461,42 +2448,18 @@ msgstr "Jelajahi lebih lanjut tentang Penpot"
msgid "questions.figma" msgid "questions.figma"
msgstr "Figma" msgstr "Figma"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.founder"
msgstr "Pendiri/VP"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.freelancer" msgid "questions.freelancer"
msgstr "Saya seorang pekerja lepas" msgstr "Saya seorang pekerja lepas"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.get-the-code-from-my-team-project"
msgstr "Dapatkan kode dari proyek tim saya "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.interface-design-visual-assets-design-systems"
msgstr "... desain antarmuka, aset visual, sistem desain, dll."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.invision" msgid "questions.invision"
msgstr "InVision" msgstr "InVision"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.leave-feedback-for-my-team-project"
msgstr "Tinggalkan masukan untuk proyek tim saya"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started" msgid "questions.lets-get-started"
msgstr "Mari kita mulai!" msgstr "Mari kita mulai!"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.manager"
msgstr "Pengelola Produk atau Proyek"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.marketing"
msgstr "Pemasaran"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.more-than-50" msgid "questions.more-than-50"
msgstr "Lebih dari 50" msgstr "Lebih dari 50"
@ -2505,10 +2468,6 @@ msgstr "Lebih dari 50"
msgid "questions.next" msgid "questions.next"
msgstr "Berikutnya" msgstr "Berikutnya"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none"
msgstr "Tidak ada"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.other"
msgstr "Lainnya (jelaskan)" msgstr "Lainnya (jelaskan)"
@ -2521,14 +2480,6 @@ msgstr "Saya mengerjakan proyek pribadi"
msgid "questions.previous" msgid "questions.previous"
msgstr "Sebelumnya" msgstr "Sebelumnya"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.questions-how-are-you-planning-to-use-penpot"
msgstr "Apa rencana Anda menggunakan Penpot?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role"
msgstr "Apa peran Anda?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.select-option" msgid "questions.select-option"
msgstr "Pilih opsi" msgstr "Pilih opsi"
@ -2537,48 +2488,14 @@ msgstr "Pilih opsi"
msgid "questions.sketch" msgid "questions.sketch"
msgstr "Sketch" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "Beberapa"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "Mulai" msgstr "Mulai"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start-to-work-on-my-project"
msgstr "Mulai bekerja pada proyek saya"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.student-teacher" msgid "questions.student-teacher"
msgstr "Siswa atau Guru" msgstr "Siswa atau Guru"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.team-size"
msgstr "Seberapa besar tim Anda?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.test-penpot-to-see-if-its-a-fit-for-team"
msgstr "Coba Penpot untuk tim Anda "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.try-out-before-using-penpot-on-premise"
msgstr "Coba sebelum menggunakan Penpot on-premise"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.wireframes-user-journeys-flows-navigation-trees"
msgstr "... gambar rangka, perjalanan & alur pengguna, pohon navigasi, dll."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-in-concept-ideas"
msgstr "Bekerja dalam ide konsep"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.your-feedback-will-help-us"
msgstr ""
"Masukan Anda akan membantu kami mengerti kebiasaan dan preferensi Anda "
"supaya kami dapat membuat Penpot sebuah alat yang berguna dan nyaman."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs, #: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
msgid "settings.detach" msgid "settings.detach"
msgstr "Copot" msgstr "Copot"

View file

@ -39,11 +39,6 @@ msgstr ""
"Questo è un servizio di prova, non utilizzare per il lavoro reale, i " "Questo è un servizio di prova, non utilizzare per il lavoro reale, i "
"progetti verranno eliminati periodicamente." "progetti verranno eliminati periodicamente."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Indirizzo e-mail"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Hai dimenticato la password?" msgstr "Hai dimenticato la password?"
@ -135,10 +130,6 @@ msgstr "Non hai ancora un account?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Crea un account" msgstr "Crea un account"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "È gratuito, è Open Source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Crea un account" msgstr "Crea un account"
@ -150,12 +141,6 @@ msgstr "La soluzione open source per il design e la prototipazione."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Condizioni di servizio" msgstr "Condizioni di servizio"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Creando un account, accetti le condizioni generali di servizio e "
"l'informativa sulla privacy."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Abbiamo inviato l'e-mail di verifica a" msgstr "Abbiamo inviato l'e-mail di verifica a"

View file

@ -35,10 +35,6 @@ msgstr "試してみませんか?"
msgid "auth.demo-warning" msgid "auth.demo-warning"
msgstr "このサービスはデモ版です。実際の業務には使用しないでください。" msgstr "このサービスはデモ版です。実際の業務には使用しないでください。"
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "Eメール"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "パスワードを忘れましたか?" msgstr "パスワードを忘れましたか?"
@ -134,10 +130,6 @@ msgstr "アカウントをお持ちでない方はこちら"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "アカウントを作成" msgstr "アカウントを作成"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "フリーでオープンソースです"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "アカウントを作成" msgstr "アカウントを作成"
@ -149,10 +141,6 @@ msgstr "デザインとプロトタイピングのためのオープンソース
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "利用規約" msgstr "利用規約"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr "サービスに登録するには、利用規約とプライバシーポリシーに同意する必要があります。"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "認証メールを送信しました" msgstr "認証メールを送信しました"

View file

@ -27,10 +27,6 @@ msgstr "데모 계정을 생성하세요"
msgid "auth.create-demo-profile" msgid "auth.create-demo-profile"
msgstr "그냥 해볼까요?" msgstr "그냥 해볼까요?"
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "이메일"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "비밀번호를 잊어버리셨나요?" msgstr "비밀번호를 잊어버리셨나요?"

View file

@ -41,10 +41,6 @@ msgstr ""
"Tai yra DEMONSTRACINĖ versija, NEKURKITE tikrų darbų, nes projektai " "Tai yra DEMONSTRACINĖ versija, NEKURKITE tikrų darbų, nes projektai "
"periodiškai - šalinami." "periodiškai - šalinami."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "El. paštas"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Pamiršote slaptažodį?" msgstr "Pamiršote slaptažodį?"
@ -141,10 +137,6 @@ msgstr "Dar neturite paskyros?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Sukurti paskyrą" msgstr "Sukurti paskyrą"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Tai - nemokama, tai - atviras kodas"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Sukurti paskyrą" msgstr "Sukurti paskyrą"
@ -156,12 +148,6 @@ msgstr "Atviro kodo dizaino ir prototipų kūrimo sprendimas."
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "Paslaugų teikimo sąlygos" msgstr "Paslaugų teikimo sąlygos"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"Kurdami naują paskyrą sutinkate su mūsų paslaugų teikimo sąlygomis ir "
"privatumo politika."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "Išsiuntėme patvirtinimo el. laišką adresu" msgstr "Išsiuntėme patvirtinimo el. laišką adresu"

View file

@ -40,11 +40,6 @@ msgstr ""
"Šis ir IZRĀDĪŠANAS pakalpojums, kas NAV IZMANTOJAMS īstam darbam, jo " "Šis ir IZRĀDĪŠANAS pakalpojums, kas NAV IZMANTOJAMS īstam darbam, jo "
"projekti ik pēc noteikta laika posma tiks izdzēsti." "projekti ik pēc noteikta laika posma tiks izdzēsti."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "E-pasta adrese"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Aizmirsta parole?" msgstr "Aizmirsta parole?"
@ -162,10 +157,6 @@ msgstr "Vēl nav konta?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Izveidot kontu" msgstr "Izveidot kontu"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Tas ir bezmaksas, tā ir atvērtā pirmkoda programmatūra"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Izveidot kontu" msgstr "Izveidot kontu"
@ -2485,10 +2476,6 @@ msgstr "2-10"
msgid "questions.31-50" msgid "questions.31-50"
msgstr "31-50" msgstr "31-50"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot"
msgstr "Plaša"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
msgstr "Adobe XD" msgstr "Adobe XD"
@ -2525,22 +2512,10 @@ msgstr "Dibinātājs/viceprezidents"
msgid "questions.freelancer" msgid "questions.freelancer"
msgstr "Esmu ārštātnieks(-ce)/Pašnodarbināts(-ā)" msgstr "Esmu ārštātnieks(-ce)/Pašnodarbināts(-ā)"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.get-the-code-from-my-team-project"
msgstr "Koda iegūšana no manas grupas projekta "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.interface-design-visual-assets-design-systems"
msgstr "... saskarnes dizains, vizuālie līdzekļi, dizaina sistēmas utt."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.invision" msgid "questions.invision"
msgstr "InVision" msgstr "InVision"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.leave-feedback-for-my-team-project"
msgstr "Atstāt atsauksmes par manas grupas projektu"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started" msgid "questions.lets-get-started"
msgstr "Ķeramies pie darba!" msgstr "Ķeramies pie darba!"
@ -2565,10 +2540,6 @@ msgstr "Neviens"
msgid "questions.next" msgid "questions.next"
msgstr "Nākamais" msgstr "Nākamais"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none"
msgstr "Nav"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.other"
msgstr "Cits (jānorāda)" msgstr "Cits (jānorāda)"
@ -2597,10 +2568,6 @@ msgstr "Atlasīt iespēju"
msgid "questions.sketch" msgid "questions.sketch"
msgstr "Sketch" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "Nelielā"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "Sākt" msgstr "Sākt"

View file

@ -39,10 +39,6 @@ msgstr ""
"ഇതൊരു ഡെമോ സേവനമാണ്, ഒരു യഥാർത്ഥ ജോലിക്ക് ഉപയോഗിക്കരുത്, പ്രൊജക്റ്റുകൾ " "ഇതൊരു ഡെമോ സേവനമാണ്, ഒരു യഥാർത്ഥ ജോലിക്ക് ഉപയോഗിക്കരുത്, പ്രൊജക്റ്റുകൾ "
"നിശ്ചിതസമയങ്ങളിൽ മായ്ക്കപ്പെടും." "നിശ്ചിതസമയങ്ങളിൽ മായ്ക്കപ്പെടും."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "ഇമെയിൽ"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "പാസ്‌വേഡ് മറന്നോ?" msgstr "പാസ്‌വേഡ് മറന്നോ?"
@ -138,10 +134,6 @@ msgstr "ഇതുവരെ അക്കൗണ്ട് ഇല്ലേ?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "അക്കൗണ്ട് സൃഷ്ടിക്കുക" msgstr "അക്കൗണ്ട് സൃഷ്ടിക്കുക"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "ഇത് സൗജന്യമാണ്, ഇത് ഓപ്പൺ സോഴ്സാണ്"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "അക്കൗണ്ട് സൃഷ്ടിക്കുക" msgstr "അക്കൗണ്ട് സൃഷ്ടിക്കുക"
@ -153,12 +145,6 @@ msgstr "ഡിസൈനിങിനും പ്രോട്ടോടൈപ്
msgid "auth.terms-of-service" msgid "auth.terms-of-service"
msgstr "ഉപയോഗനിബന്ധനകൾ" msgstr "ഉപയോഗനിബന്ധനകൾ"
#: src/app/main/ui/auth/register.cljs
msgid "auth.terms-privacy-agreement"
msgstr ""
"ഒരു അക്കൗണ്ട് സൃഷ്ടിക്കുമ്പോൾ, നിങ്ങൾ ഞങ്ങളുടെ ഉപയോഗനിബന്ധനകളും "
"സ്വകാര്യതാനയവും അംഗീകരിക്കുന്നു."
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.verification-email-sent" msgid "auth.verification-email-sent"
msgstr "സാധൂകരിക്കാനുള്ള ഇമെയിൽ ഞങ്ങൾ അയച്ചിരിക്കുന്നു" msgstr "സാധൂകരിക്കാനുള്ള ഇമെയിൽ ഞങ്ങൾ അയച്ചിരിക്കുന്നു"

View file

@ -25,10 +25,6 @@ msgstr ""
"Ini adalah perkhidmatan DEMO, JANGAN GUNAKAN untuk kerja sebenar, projek " "Ini adalah perkhidmatan DEMO, JANGAN GUNAKAN untuk kerja sebenar, projek "
"akan dipadam secara berkala." "akan dipadam secara berkala."
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "E-mel"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Lupa kata laluan?" msgstr "Lupa kata laluan?"

View file

@ -15,11 +15,6 @@ msgstr ""
msgid "auth.confirm-password" msgid "auth.confirm-password"
msgstr "Bekreft passord" msgstr "Bekreft passord"
#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
#, fuzzy
msgid "auth.email"
msgstr "E-post"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Glemt passordet?" msgstr "Glemt passordet?"

View file

@ -39,11 +39,6 @@ msgstr ""
"Dit is een DEMO-service, GEBRUIK DIT NIET voor echt werk, de projecten " "Dit is een DEMO-service, GEBRUIK DIT NIET voor echt werk, de projecten "
"worden regelmatig gewist." "worden regelmatig gewist."
#: src/app/main/ui/auth/register.cljs,
#: src/app/main/ui/auth/recovery_request.cljs, src/app/main/ui/auth/login.cljs
msgid "auth.email"
msgstr "E-mail"
#: src/app/main/ui/auth/login.cljs #: src/app/main/ui/auth/login.cljs
msgid "auth.forgot-password" msgid "auth.forgot-password"
msgstr "Wachtwoord vergeten?" msgstr "Wachtwoord vergeten?"
@ -173,10 +168,6 @@ msgstr "Nog geen account?"
msgid "auth.register-submit" msgid "auth.register-submit"
msgstr "Account aanmaken" msgstr "Account aanmaken"
#: src/app/main/ui/auth/register.cljs
msgid "auth.register-subtitle"
msgstr "Het is gratis, het is open source"
#: src/app/main/ui/auth/register.cljs #: src/app/main/ui/auth/register.cljs
msgid "auth.register-title" msgid "auth.register-title"
msgstr "Account aanmaken" msgstr "Account aanmaken"
@ -2503,10 +2494,6 @@ msgstr "2-10"
msgid "questions.31-50" msgid "questions.31-50"
msgstr "31-50" msgstr "31-50"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.a-lot"
msgstr "Veel"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.adobe-xd" msgid "questions.adobe-xd"
msgstr "Adobe XD" msgstr "Adobe XD"
@ -2515,62 +2502,22 @@ msgstr "Adobe XD"
msgid "questions.canva" msgid "questions.canva"
msgstr "Canva" msgstr "Canva"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.describe-your-experience-working-on"
msgstr "Hoe zou je je ervaring omschrijven voor het werken aan..."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.designer"
msgstr "Ontwerper"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.developer"
msgstr "Ontwikkelaar"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.discover-more-about-penpot"
msgstr "Meer over Penpot ontdekken"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.figma" msgid "questions.figma"
msgstr "Figma" msgstr "Figma"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.founder"
msgstr "Oprichter/VP"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.freelancer" msgid "questions.freelancer"
msgstr "Ik ben een freelancer" msgstr "Ik ben een freelancer"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.get-the-code-from-my-team-project"
msgstr "Haal de code op van mijn teamproject "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.interface-design-visual-assets-design-systems"
msgstr "... interfaceontwerp, visuel assets, design systems, enz."
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.invision" msgid "questions.invision"
msgstr "InVision" msgstr "InVision"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.leave-feedback-for-my-team-project"
msgstr "Laat feedback achter voor mijn teamproject"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.lets-get-started" msgid "questions.lets-get-started"
msgstr "Laten we beginnen!" msgstr "Laten we beginnen!"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.manager"
msgstr "Product- of projectmanager"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.marketing"
msgstr "Marketing"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.more-than-50" msgid "questions.more-than-50"
msgstr "Meer dan 50" msgstr "Meer dan 50"
@ -2583,10 +2530,6 @@ msgstr "Geen"
msgid "questions.next" msgid "questions.next"
msgstr "Volgende" msgstr "Volgende"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.none"
msgstr "Geen"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.other" msgid "questions.other"
msgstr "Anders (namelijk…)" msgstr "Anders (namelijk…)"
@ -2599,14 +2542,6 @@ msgstr "Ik werk aan een persoonlijk project"
msgid "questions.previous" msgid "questions.previous"
msgstr "Vorige" msgstr "Vorige"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.questions-how-are-you-planning-to-use-penpot"
msgstr "Hoe ben je van plan Penpot te gebruiken?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.role"
msgstr "Wat is je rol?"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.select-option" msgid "questions.select-option"
msgstr "Selecteer een optie" msgstr "Selecteer een optie"
@ -2615,50 +2550,14 @@ msgstr "Selecteer een optie"
msgid "questions.sketch" msgid "questions.sketch"
msgstr "Sketch" msgstr "Sketch"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.some"
msgstr "Sommige"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start" msgid "questions.start"
msgstr "Starten" msgstr "Starten"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.start-to-work-on-my-project"
msgstr "Begin aan mijn project te werken"
#: src/app/main/ui/onboarding/questions.cljs #: src/app/main/ui/onboarding/questions.cljs
msgid "questions.student-teacher" msgid "questions.student-teacher"
msgstr "Student of docent" msgstr "Student of docent"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.team-size"
msgstr "Hoe groot is je team?"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.test-penpot-to-see-if-its-a-fit-for-team"
msgstr "Penpot testen om te zien of het geschikt is voor het team "
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.try-out-before-using-penpot-on-premise"
msgstr "Probeer uit voordat je Penpot on-premise gebruikt"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.wireframes-user-journeys-flows-navigation-trees"
msgstr ""
"… draadmodellen, gebruikers journeys en stroomdiagrammen, navigatiebomen, "
"etc."
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.work-in-concept-ideas"
msgstr "Werken in conceptideeën"
#: src/app/main/ui/onboarding/questions.cljs
msgid "questions.your-feedback-will-help-us"
msgstr ""
"Jouw feedback helpt ons te begrijpen wat je gewoonten en voorkeuren zijn, "
"zodat we van Penpot een nuttig en plezierig hulpmiddel kunnen blijven maken."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs, #: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
msgid "settings.detach" msgid "settings.detach"
msgstr "Ontkoppelen" msgstr "Ontkoppelen"

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