@nextsparkjs/theme-productivity 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -0
- package/about.md +123 -0
- package/components/CardDetailModal.tsx +318 -0
- package/components/KanbanBoard.tsx +612 -0
- package/components/KanbanCard.tsx +218 -0
- package/components/KanbanColumn.tsx +264 -0
- package/components/SortableList.tsx +46 -0
- package/components/index.ts +4 -0
- package/config/app.config.ts +172 -0
- package/config/billing.config.ts +187 -0
- package/config/dashboard.config.ts +357 -0
- package/config/dev.config.ts +55 -0
- package/config/features.config.ts +256 -0
- package/config/flows.config.ts +484 -0
- package/config/permissions.config.ts +167 -0
- package/config/theme.config.ts +106 -0
- package/entities/boards/boards.config.ts +61 -0
- package/entities/boards/boards.fields.ts +154 -0
- package/entities/boards/boards.service.ts +256 -0
- package/entities/boards/boards.types.ts +57 -0
- package/entities/boards/messages/en.json +80 -0
- package/entities/boards/messages/es.json +80 -0
- package/entities/boards/migrations/001_boards_table.sql +83 -0
- package/entities/cards/cards.config.ts +61 -0
- package/entities/cards/cards.fields.ts +242 -0
- package/entities/cards/cards.service.ts +336 -0
- package/entities/cards/cards.types.ts +79 -0
- package/entities/cards/messages/en.json +114 -0
- package/entities/cards/messages/es.json +114 -0
- package/entities/cards/migrations/020_cards_table.sql +92 -0
- package/entities/lists/lists.config.ts +61 -0
- package/entities/lists/lists.fields.ts +105 -0
- package/entities/lists/lists.service.ts +252 -0
- package/entities/lists/lists.types.ts +55 -0
- package/entities/lists/messages/en.json +60 -0
- package/entities/lists/messages/es.json +60 -0
- package/entities/lists/migrations/010_lists_table.sql +79 -0
- package/lib/selectors.ts +206 -0
- package/messages/en.json +79 -0
- package/messages/es.json +79 -0
- package/migrations/999_theme_sample_data.sql +922 -0
- package/migrations/999a_initial_sample_data.sql +377 -0
- package/migrations/999b_abundant_sample_data.sql +346 -0
- package/package.json +17 -0
- package/permissions-matrix.md +122 -0
- package/styles/components.css +460 -0
- package/styles/globals.css +560 -0
- package/templates/dashboard/(main)/boards/[id]/[cardId]/page.tsx +238 -0
- package/templates/dashboard/(main)/boards/[id]/edit/page.tsx +390 -0
- package/templates/dashboard/(main)/boards/[id]/page.tsx +236 -0
- package/templates/dashboard/(main)/boards/create/page.tsx +236 -0
- package/templates/dashboard/(main)/boards/page.tsx +335 -0
- package/templates/dashboard/(main)/layout.tsx +32 -0
- package/templates/dashboard/(main)/page.tsx +592 -0
- package/templates/shared/ProductivityMobileNav.tsx +410 -0
- package/templates/shared/ProductivitySidebar.tsx +538 -0
- package/templates/shared/ProductivityTopBar.tsx +317 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- Lists Table Migration
|
|
3
|
+
-- Productivity theme: Columns within boards
|
|
4
|
+
-- ============================================================================
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS "lists" (
|
|
7
|
+
"id" TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
8
|
+
"name" VARCHAR(255) NOT NULL,
|
|
9
|
+
"position" INTEGER DEFAULT 0,
|
|
10
|
+
"boardId" TEXT NOT NULL REFERENCES "boards"("id") ON DELETE CASCADE,
|
|
11
|
+
"userId" TEXT NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
|
12
|
+
"teamId" TEXT NOT NULL REFERENCES "teams"("id") ON DELETE CASCADE,
|
|
13
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
14
|
+
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
-- Indexes
|
|
18
|
+
CREATE INDEX IF NOT EXISTS "lists_boardId_idx" ON "lists" ("boardId");
|
|
19
|
+
CREATE INDEX IF NOT EXISTS "lists_teamId_idx" ON "lists" ("teamId");
|
|
20
|
+
CREATE INDEX IF NOT EXISTS "lists_position_idx" ON "lists" ("boardId", "position");
|
|
21
|
+
|
|
22
|
+
-- Enable RLS
|
|
23
|
+
ALTER TABLE "lists" ENABLE ROW LEVEL SECURITY;
|
|
24
|
+
|
|
25
|
+
-- Drop existing policies
|
|
26
|
+
DROP POLICY IF EXISTS "lists_select_policy" ON "lists";
|
|
27
|
+
DROP POLICY IF EXISTS "lists_insert_policy" ON "lists";
|
|
28
|
+
DROP POLICY IF EXISTS "lists_update_policy" ON "lists";
|
|
29
|
+
DROP POLICY IF EXISTS "lists_delete_policy" ON "lists";
|
|
30
|
+
|
|
31
|
+
-- Policy: Team members can view lists
|
|
32
|
+
CREATE POLICY "lists_select_policy" ON "lists"
|
|
33
|
+
FOR SELECT TO authenticated
|
|
34
|
+
USING (
|
|
35
|
+
"teamId" = ANY(public.get_user_team_ids())
|
|
36
|
+
OR public.is_superadmin()
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Policy: Team members can create lists
|
|
40
|
+
CREATE POLICY "lists_insert_policy" ON "lists"
|
|
41
|
+
FOR INSERT TO authenticated
|
|
42
|
+
WITH CHECK (
|
|
43
|
+
"teamId" = ANY(public.get_user_team_ids())
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- Policy: Team members can update lists
|
|
47
|
+
CREATE POLICY "lists_update_policy" ON "lists"
|
|
48
|
+
FOR UPDATE TO authenticated
|
|
49
|
+
USING (
|
|
50
|
+
"teamId" = ANY(public.get_user_team_ids())
|
|
51
|
+
OR public.is_superadmin()
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
-- Policy: Team members can delete lists (owner only at app level)
|
|
55
|
+
CREATE POLICY "lists_delete_policy" ON "lists"
|
|
56
|
+
FOR DELETE TO authenticated
|
|
57
|
+
USING (
|
|
58
|
+
"teamId" = ANY(public.get_user_team_ids())
|
|
59
|
+
OR public.is_superadmin()
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
-- Trigger for updatedAt
|
|
63
|
+
CREATE OR REPLACE FUNCTION update_lists_updated_at()
|
|
64
|
+
RETURNS TRIGGER AS $$
|
|
65
|
+
BEGIN
|
|
66
|
+
NEW."updatedAt" = NOW();
|
|
67
|
+
RETURN NEW;
|
|
68
|
+
END;
|
|
69
|
+
$$ LANGUAGE plpgsql;
|
|
70
|
+
|
|
71
|
+
DROP TRIGGER IF EXISTS lists_updated_at_trigger ON "lists";
|
|
72
|
+
CREATE TRIGGER lists_updated_at_trigger
|
|
73
|
+
BEFORE UPDATE ON "lists"
|
|
74
|
+
FOR EACH ROW
|
|
75
|
+
EXECUTE FUNCTION update_lists_updated_at();
|
|
76
|
+
|
|
77
|
+
-- Comments
|
|
78
|
+
COMMENT ON TABLE "lists" IS 'Columns within boards (To Do, In Progress, Done, etc.)';
|
|
79
|
+
COMMENT ON COLUMN "lists"."position" IS 'Display order within the parent board';
|
package/lib/selectors.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Productivity Theme - Block Selectors
|
|
3
|
+
*
|
|
4
|
+
* This file defines selectors for block components in the theme.
|
|
5
|
+
* It's placed in lib/ instead of tests/ so TypeScript can resolve imports.
|
|
6
|
+
*
|
|
7
|
+
* Used by:
|
|
8
|
+
* - Block components (for data-cy attributes)
|
|
9
|
+
* - Cypress tests (via tests/cypress/src/selectors.ts)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createSelectorHelpers } from '@nextsparkjs/core/lib/test/selector-factory'
|
|
13
|
+
import { CORE_SELECTORS } from '@nextsparkjs/core/lib/test/core-selectors'
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// BLOCK SELECTORS
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Block-specific selectors for the productivity theme.
|
|
21
|
+
* Each block has at minimum a 'container' selector.
|
|
22
|
+
* Dynamic selectors use {index} placeholder.
|
|
23
|
+
*/
|
|
24
|
+
export const BLOCK_SELECTORS = {
|
|
25
|
+
// Productivity theme currently has no custom blocks
|
|
26
|
+
// Add block selectors here when blocks are created
|
|
27
|
+
} as const
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// ENTITY SELECTORS
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Entity-specific selectors for the productivity theme.
|
|
35
|
+
*/
|
|
36
|
+
export const ENTITY_SELECTORS = {
|
|
37
|
+
boards: {
|
|
38
|
+
list: 'boards-list',
|
|
39
|
+
listItem: 'board-item-{index}',
|
|
40
|
+
card: 'board-card-{id}',
|
|
41
|
+
name: 'board-name',
|
|
42
|
+
description: 'board-description',
|
|
43
|
+
createButton: 'board-create-button',
|
|
44
|
+
editButton: 'board-edit-button',
|
|
45
|
+
deleteButton: 'board-delete-button',
|
|
46
|
+
settingsButton: 'board-settings-button',
|
|
47
|
+
form: {
|
|
48
|
+
container: 'board-form',
|
|
49
|
+
name: 'board-form-name',
|
|
50
|
+
description: 'board-form-description',
|
|
51
|
+
submit: 'board-form-submit',
|
|
52
|
+
cancel: 'board-form-cancel',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
lists: {
|
|
56
|
+
container: 'list-container-{id}',
|
|
57
|
+
header: 'list-header-{id}',
|
|
58
|
+
name: 'list-name',
|
|
59
|
+
cardsContainer: 'list-cards-{id}',
|
|
60
|
+
addCardButton: 'list-add-card-{id}',
|
|
61
|
+
createButton: 'list-create-button',
|
|
62
|
+
editButton: 'list-edit-button',
|
|
63
|
+
deleteButton: 'list-delete-button',
|
|
64
|
+
moveHandle: 'list-move-handle-{id}',
|
|
65
|
+
form: {
|
|
66
|
+
container: 'list-form',
|
|
67
|
+
name: 'list-form-name',
|
|
68
|
+
submit: 'list-form-submit',
|
|
69
|
+
cancel: 'list-form-cancel',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
cards: {
|
|
73
|
+
container: 'card-container-{id}',
|
|
74
|
+
title: 'card-title',
|
|
75
|
+
description: 'card-description',
|
|
76
|
+
dueDate: 'card-due-date',
|
|
77
|
+
assignee: 'card-assignee',
|
|
78
|
+
labels: 'card-labels',
|
|
79
|
+
createButton: 'card-create-button',
|
|
80
|
+
editButton: 'card-edit-button',
|
|
81
|
+
deleteButton: 'card-delete-button',
|
|
82
|
+
moveHandle: 'card-move-handle-{id}',
|
|
83
|
+
form: {
|
|
84
|
+
container: 'card-form',
|
|
85
|
+
title: 'card-form-title',
|
|
86
|
+
description: 'card-form-description',
|
|
87
|
+
dueDate: 'card-form-due-date',
|
|
88
|
+
assignee: 'card-form-assignee',
|
|
89
|
+
labels: 'card-form-labels',
|
|
90
|
+
submit: 'card-form-submit',
|
|
91
|
+
cancel: 'card-form-cancel',
|
|
92
|
+
},
|
|
93
|
+
detail: {
|
|
94
|
+
modal: 'card-detail-modal',
|
|
95
|
+
header: 'card-detail-header',
|
|
96
|
+
body: 'card-detail-body',
|
|
97
|
+
comments: 'card-detail-comments',
|
|
98
|
+
attachments: 'card-detail-attachments',
|
|
99
|
+
checklist: 'card-detail-checklist',
|
|
100
|
+
closeButton: 'card-detail-close',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
} as const
|
|
104
|
+
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// KANBAN-SPECIFIC SELECTORS
|
|
107
|
+
// =============================================================================
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Kanban-specific UI selectors.
|
|
111
|
+
*/
|
|
112
|
+
export const KANBAN_SELECTORS = {
|
|
113
|
+
board: {
|
|
114
|
+
container: 'kanban-board',
|
|
115
|
+
header: 'kanban-board-header',
|
|
116
|
+
listsContainer: 'kanban-lists-container',
|
|
117
|
+
addListButton: 'kanban-add-list-button',
|
|
118
|
+
settings: 'kanban-board-settings',
|
|
119
|
+
},
|
|
120
|
+
dragDrop: {
|
|
121
|
+
dragging: 'dragging',
|
|
122
|
+
dragHandle: 'drag-handle',
|
|
123
|
+
dropZone: 'drop-zone-{id}',
|
|
124
|
+
dropIndicator: 'drop-indicator',
|
|
125
|
+
placeholder: 'drag-placeholder',
|
|
126
|
+
},
|
|
127
|
+
filters: {
|
|
128
|
+
container: 'kanban-filters',
|
|
129
|
+
search: 'kanban-search',
|
|
130
|
+
assigneeFilter: 'kanban-assignee-filter',
|
|
131
|
+
labelFilter: 'kanban-label-filter',
|
|
132
|
+
dueDateFilter: 'kanban-due-date-filter',
|
|
133
|
+
clearFilters: 'kanban-clear-filters',
|
|
134
|
+
},
|
|
135
|
+
} as const
|
|
136
|
+
|
|
137
|
+
// =============================================================================
|
|
138
|
+
// THEME SELECTORS (CORE + BLOCKS + ENTITIES + KANBAN)
|
|
139
|
+
// =============================================================================
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Complete theme selectors merging core, blocks, and entities.
|
|
143
|
+
*/
|
|
144
|
+
export const THEME_SELECTORS = {
|
|
145
|
+
...CORE_SELECTORS,
|
|
146
|
+
blocks: BLOCK_SELECTORS,
|
|
147
|
+
entities: ENTITY_SELECTORS,
|
|
148
|
+
kanban: KANBAN_SELECTORS,
|
|
149
|
+
} as const
|
|
150
|
+
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// EXPORTS
|
|
153
|
+
// =============================================================================
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Create helpers bound to theme selectors
|
|
157
|
+
*/
|
|
158
|
+
const helpers = createSelectorHelpers(THEME_SELECTORS)
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Full selectors object (core + theme extensions)
|
|
162
|
+
*/
|
|
163
|
+
export const SELECTORS = helpers.SELECTORS
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get a selector value by path
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* sel('auth.login.form') // 'login-form'
|
|
170
|
+
* sel('entities.boards.list') // 'boards-list'
|
|
171
|
+
* sel('entities.cards.container', { id: 'abc123' }) // 'card-container-abc123'
|
|
172
|
+
*/
|
|
173
|
+
export const sel = helpers.sel
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Alias for sel
|
|
177
|
+
*/
|
|
178
|
+
export const s = helpers.s
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get selector only in dev/test environments
|
|
182
|
+
*/
|
|
183
|
+
export const selDev = helpers.selDev
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get Cypress selector string [data-cy="..."]
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* cySelector('entities.boards.list') // '[data-cy="boards-list"]'
|
|
190
|
+
*/
|
|
191
|
+
export const cySelector = helpers.cySelector
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Create entity-specific selector helpers
|
|
195
|
+
*/
|
|
196
|
+
export const entitySelectors = helpers.entitySelectors
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Type exports
|
|
200
|
+
*/
|
|
201
|
+
export type ThemeSelectorsType = typeof THEME_SELECTORS
|
|
202
|
+
export type BlockSelectorsType = typeof BLOCK_SELECTORS
|
|
203
|
+
export type EntitySelectorsType = typeof ENTITY_SELECTORS
|
|
204
|
+
export type KanbanSelectorsType = typeof KANBAN_SELECTORS
|
|
205
|
+
export type { Replacements } from '@nextsparkjs/core/lib/test/selector-factory'
|
|
206
|
+
export { CORE_SELECTORS }
|
package/messages/en.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"productivity": {
|
|
3
|
+
"name": "Productivity",
|
|
4
|
+
"description": "A collaborative task management app",
|
|
5
|
+
"tagline": "Organize your work, together",
|
|
6
|
+
|
|
7
|
+
"navigation": {
|
|
8
|
+
"boards": "Boards",
|
|
9
|
+
"myCards": "My Cards",
|
|
10
|
+
"calendar": "Calendar",
|
|
11
|
+
"team": "Team"
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"quickActions": {
|
|
15
|
+
"createBoard": "Create Board",
|
|
16
|
+
"createCard": "Add Card"
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
"dashboard": {
|
|
20
|
+
"welcome": "Welcome back!",
|
|
21
|
+
"welcomeWithName": "Welcome back, {name}!",
|
|
22
|
+
"overview": "Your Overview",
|
|
23
|
+
"recentBoards": "Recent Boards",
|
|
24
|
+
"upcomingDeadlines": "Upcoming Deadlines",
|
|
25
|
+
"assignedToYou": "Assigned to You",
|
|
26
|
+
"teamActivity": "Team Activity"
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
"stats": {
|
|
30
|
+
"totalBoards": "Total Boards",
|
|
31
|
+
"totalCards": "Total Cards",
|
|
32
|
+
"cardsCompleted": "Cards Completed",
|
|
33
|
+
"cardsDueThisWeek": "Due This Week"
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
"empty": {
|
|
37
|
+
"noBoards": {
|
|
38
|
+
"title": "No boards yet",
|
|
39
|
+
"description": "Create your first board to start organizing your work.",
|
|
40
|
+
"action": "Create your first board"
|
|
41
|
+
},
|
|
42
|
+
"noAssignedCards": {
|
|
43
|
+
"title": "No cards assigned",
|
|
44
|
+
"description": "Cards assigned to you will appear here."
|
|
45
|
+
},
|
|
46
|
+
"noDeadlines": {
|
|
47
|
+
"title": "No upcoming deadlines",
|
|
48
|
+
"description": "Cards with due dates will appear here."
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
"collaboration": {
|
|
53
|
+
"invite": "Invite Team Member",
|
|
54
|
+
"inviteDescription": "Invite someone to collaborate on your boards",
|
|
55
|
+
"teamMembers": "Team Members",
|
|
56
|
+
"roles": {
|
|
57
|
+
"owner": "Owner",
|
|
58
|
+
"member": "Member",
|
|
59
|
+
"viewer": "Viewer"
|
|
60
|
+
},
|
|
61
|
+
"roleDescriptions": {
|
|
62
|
+
"owner": "Full access to all boards, lists, and cards. Can invite members.",
|
|
63
|
+
"member": "Can create and edit lists and cards. Cannot delete boards.",
|
|
64
|
+
"viewer": "Read-only access to all boards, lists, and cards."
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
"shortcuts": {
|
|
69
|
+
"title": "Keyboard Shortcuts",
|
|
70
|
+
"newCard": "New Card",
|
|
71
|
+
"newBoard": "New Board",
|
|
72
|
+
"search": "Search",
|
|
73
|
+
"toggleSidebar": "Toggle Sidebar",
|
|
74
|
+
"nextList": "Next List",
|
|
75
|
+
"previousList": "Previous List"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
package/messages/es.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"productivity": {
|
|
3
|
+
"name": "Productivity",
|
|
4
|
+
"description": "Una app colaborativa de gestión de tareas",
|
|
5
|
+
"tagline": "Organiza tu trabajo, en equipo",
|
|
6
|
+
|
|
7
|
+
"navigation": {
|
|
8
|
+
"boards": "Tableros",
|
|
9
|
+
"myCards": "Mis Tarjetas",
|
|
10
|
+
"calendar": "Calendario",
|
|
11
|
+
"team": "Equipo"
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
"quickActions": {
|
|
15
|
+
"createBoard": "Crear Tablero",
|
|
16
|
+
"createCard": "Agregar Tarjeta"
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
"dashboard": {
|
|
20
|
+
"welcome": "¡Bienvenido de nuevo!",
|
|
21
|
+
"welcomeWithName": "¡Bienvenido de nuevo, {name}!",
|
|
22
|
+
"overview": "Tu Resumen",
|
|
23
|
+
"recentBoards": "Tableros Recientes",
|
|
24
|
+
"upcomingDeadlines": "Próximas Fechas Límite",
|
|
25
|
+
"assignedToYou": "Asignadas a Ti",
|
|
26
|
+
"teamActivity": "Actividad del Equipo"
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
"stats": {
|
|
30
|
+
"totalBoards": "Total de Tableros",
|
|
31
|
+
"totalCards": "Total de Tarjetas",
|
|
32
|
+
"cardsCompleted": "Tarjetas Completadas",
|
|
33
|
+
"cardsDueThisWeek": "Vencen Esta Semana"
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
"empty": {
|
|
37
|
+
"noBoards": {
|
|
38
|
+
"title": "Aún no hay tableros",
|
|
39
|
+
"description": "Crea tu primer tablero para comenzar a organizar tu trabajo.",
|
|
40
|
+
"action": "Crear tu primer tablero"
|
|
41
|
+
},
|
|
42
|
+
"noAssignedCards": {
|
|
43
|
+
"title": "Sin tarjetas asignadas",
|
|
44
|
+
"description": "Las tarjetas asignadas a ti aparecerán aquí."
|
|
45
|
+
},
|
|
46
|
+
"noDeadlines": {
|
|
47
|
+
"title": "Sin fechas límite próximas",
|
|
48
|
+
"description": "Las tarjetas con fechas de vencimiento aparecerán aquí."
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
"collaboration": {
|
|
53
|
+
"invite": "Invitar Miembro del Equipo",
|
|
54
|
+
"inviteDescription": "Invita a alguien a colaborar en tus tableros",
|
|
55
|
+
"teamMembers": "Miembros del Equipo",
|
|
56
|
+
"roles": {
|
|
57
|
+
"owner": "Propietario",
|
|
58
|
+
"member": "Miembro",
|
|
59
|
+
"viewer": "Visor"
|
|
60
|
+
},
|
|
61
|
+
"roleDescriptions": {
|
|
62
|
+
"owner": "Acceso completo a todos los tableros, listas y tarjetas. Puede invitar miembros.",
|
|
63
|
+
"member": "Puede crear y editar listas y tarjetas. No puede eliminar tableros.",
|
|
64
|
+
"viewer": "Acceso de solo lectura a todos los tableros, listas y tarjetas."
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
"shortcuts": {
|
|
69
|
+
"title": "Atajos de Teclado",
|
|
70
|
+
"newCard": "Nueva Tarjeta",
|
|
71
|
+
"newBoard": "Nuevo Tablero",
|
|
72
|
+
"search": "Buscar",
|
|
73
|
+
"toggleSidebar": "Alternar Barra Lateral",
|
|
74
|
+
"nextList": "Lista Siguiente",
|
|
75
|
+
"previousList": "Lista Anterior"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|