feat: improve Jira URL UX and settings editing
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
let saving = false
|
||||
let meetingLimitMin = 15
|
||||
let defaultTimeMin = 2
|
||||
let defaultJiraUrl = ''
|
||||
let editingDefaultJiraUrl = false
|
||||
let defaultJiraUrlInput = ''
|
||||
let windowWidth = 800
|
||||
let windowFullHeight = true
|
||||
let audioContext = null
|
||||
@@ -236,6 +239,7 @@
|
||||
}
|
||||
if (settings) {
|
||||
defaultTimeMin = Math.floor(settings.defaultParticipantTime / 60)
|
||||
defaultJiraUrl = settings.defaultJiraUrl || 'https://jira.ncloudtech.ru/secure/RapidBoard.jspa?rapidView=1431&projectKey=RNDIN'
|
||||
windowWidth = settings.windowWidth || 800
|
||||
windowFullHeight = settings.windowFullHeight !== false
|
||||
}
|
||||
@@ -251,6 +255,7 @@
|
||||
saving = true
|
||||
try {
|
||||
settings.defaultParticipantTime = defaultTimeMin * 60
|
||||
settings.defaultJiraUrl = defaultJiraUrl.trim()
|
||||
meeting.timeLimit = meetingLimitMin * 60
|
||||
settings.windowWidth = Math.max(480, windowWidth)
|
||||
settings.windowFullHeight = windowFullHeight
|
||||
@@ -312,6 +317,29 @@
|
||||
<label for="meetingLimit">{$t('settings.defaultTotalTime')}</label>
|
||||
<input type="number" id="meetingLimit" bind:value={meetingLimitMin} min="1" max="120" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="defaultJiraUrl">{$t('settings.defaultJiraUrl')}</label>
|
||||
{#if editingDefaultJiraUrl}
|
||||
<div class="jira-edit-inline">
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input type="url" bind:value={defaultJiraUrlInput} autofocus
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') { defaultJiraUrl = defaultJiraUrlInput; editingDefaultJiraUrl = false }
|
||||
if (e.key === 'Escape') editingDefaultJiraUrl = false
|
||||
}}
|
||||
/>
|
||||
<button class="jira-inline-save" on:click={() => { defaultJiraUrl = defaultJiraUrlInput; editingDefaultJiraUrl = false }}>✓</button>
|
||||
<button class="jira-inline-cancel" on:click={() => editingDefaultJiraUrl = false}>✗</button>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||
<div class="jira-display" on:click={() => { defaultJiraUrlInput = defaultJiraUrl; editingDefaultJiraUrl = true }}>
|
||||
<span class="jira-url-text">{defaultJiraUrl || '—'}</span>
|
||||
<span class="jira-edit-icon">✎</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -526,7 +554,8 @@
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"] {
|
||||
input[type="number"],
|
||||
input[type="url"] {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #3d4f61;
|
||||
@@ -830,4 +859,79 @@
|
||||
background: #3b7dc9;
|
||||
border-color: #3b7dc9;
|
||||
}
|
||||
|
||||
.jira-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
border: 1px solid #3d4f61;
|
||||
border-radius: 8px;
|
||||
background: #1b2636;
|
||||
color: #e0e0e0;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: border-color 0.15s;
|
||||
}
|
||||
|
||||
.jira-display:hover {
|
||||
border-color: #4a90d9;
|
||||
}
|
||||
|
||||
.jira-url-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.jira-edit-icon {
|
||||
flex-shrink: 0;
|
||||
margin-left: 8px;
|
||||
color: #9ca3af;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
|
||||
.jira-display:hover .jira-edit-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.jira-edit-inline {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.jira-edit-inline input {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
border: 1px solid #4a90d9;
|
||||
border-radius: 8px;
|
||||
background: #1b2636;
|
||||
color: #e0e0e0;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.jira-inline-save,
|
||||
.jira-inline-cancel {
|
||||
flex-shrink: 0;
|
||||
width: 36px;
|
||||
height: 42px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jira-inline-save {
|
||||
background: #22c55e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.jira-inline-cancel {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
import { GetParticipants, GetMeeting, StartMeeting, AddParticipant, DeleteParticipant, ReorderParticipants, UpdateParticipant, UpdateMeeting } from '../../wailsjs/go/app/App'
|
||||
import { GetParticipants, GetMeeting, StartMeeting, AddParticipant, DeleteParticipant, ReorderParticipants, UpdateParticipant, UpdateMeeting, GetSettings } from '../../wailsjs/go/app/App'
|
||||
import { t } from '../lib/i18n'
|
||||
import { attendance } from '../lib/stores'
|
||||
|
||||
@@ -19,17 +19,53 @@
|
||||
let editTimeLimitMin = 2
|
||||
let editJiraFilter = ''
|
||||
|
||||
// Quick jira filter edit
|
||||
let quickFilterEditId = null
|
||||
let quickFilterInput = ''
|
||||
|
||||
// Meeting name editing
|
||||
let editingMeetingName = false
|
||||
let meetingNameInput = ''
|
||||
let originalMeetingName = ''
|
||||
|
||||
// Meeting time editing
|
||||
let editingMeetingTime = false
|
||||
let meetingTimeInput = 60
|
||||
let originalMeetingTime = 60
|
||||
|
||||
// Meeting Jira URL editing
|
||||
let editingMeetingJiraUrl = false
|
||||
let meetingJiraUrlInput = ''
|
||||
let originalMeetingJiraUrl = ''
|
||||
let defaultJiraUrl = ''
|
||||
|
||||
// Confirmation dialog when switching between editable fields
|
||||
let confirmDialog = null
|
||||
|
||||
function isDirty() {
|
||||
if (editingMeetingName) return meetingNameInput !== originalMeetingName
|
||||
if (editingMeetingTime) return meetingTimeInput !== originalMeetingTime
|
||||
if (editingMeetingJiraUrl) return meetingJiraUrlInput !== originalMeetingJiraUrl
|
||||
return false
|
||||
}
|
||||
|
||||
function getActiveEdit() {
|
||||
if (editingMeetingName) return { save: saveMeetingName, cancel: cancelEditMeetingName }
|
||||
if (editingMeetingTime) return { save: saveMeetingTime, cancel: cancelEditMeetingTime }
|
||||
if (editingMeetingJiraUrl) return { save: saveMeetingJiraUrl, cancel: cancelEditMeetingJiraUrl }
|
||||
return null
|
||||
}
|
||||
|
||||
async function guardEdit(startFn) {
|
||||
const active = getActiveEdit()
|
||||
if (!active) { startFn(); return }
|
||||
if (!isDirty()) { active.cancel(); startFn(); return }
|
||||
confirmDialog = {
|
||||
save: async () => { confirmDialog = null; await active.save(); startFn() },
|
||||
discard: () => { confirmDialog = null; active.cancel(); startFn() },
|
||||
cancel: () => { confirmDialog = null }
|
||||
}
|
||||
}
|
||||
onMount(async () => {
|
||||
await loadData()
|
||||
})
|
||||
@@ -39,6 +75,8 @@
|
||||
try {
|
||||
participants = await GetParticipants()
|
||||
meeting = await GetMeeting()
|
||||
const appSettings = await GetSettings()
|
||||
defaultJiraUrl = appSettings?.defaultJiraUrl || 'https://jira.ncloudtech.ru/secure/RapidBoard.jspa?rapidView=1431&projectKey=RNDIN'
|
||||
|
||||
selectedOrder = participants.map(p => p.id)
|
||||
attendance.init(participants)
|
||||
@@ -78,6 +116,28 @@
|
||||
editJiraFilter = p.jiraFilter || ''
|
||||
}
|
||||
|
||||
function startQuickFilterEdit(p) {
|
||||
quickFilterEditId = p.id
|
||||
quickFilterInput = p.jiraFilter || ''
|
||||
}
|
||||
|
||||
function cancelQuickFilterEdit() {
|
||||
quickFilterEditId = null
|
||||
quickFilterInput = ''
|
||||
}
|
||||
|
||||
async function saveQuickFilterEdit() {
|
||||
const p = participants.find(x => x.id === quickFilterEditId)
|
||||
if (!p) return
|
||||
try {
|
||||
await UpdateParticipant(p.id, p.name, '', p.timeLimit, quickFilterInput.trim())
|
||||
quickFilterEditId = null
|
||||
await loadData()
|
||||
} catch (e) {
|
||||
console.error('Failed to update jira filter:', e)
|
||||
}
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
editingId = null
|
||||
editName = ''
|
||||
@@ -181,7 +241,8 @@
|
||||
}
|
||||
|
||||
function startEditMeetingName() {
|
||||
meetingNameInput = meeting?.name || ''
|
||||
originalMeetingName = meeting?.name || ''
|
||||
meetingNameInput = originalMeetingName
|
||||
editingMeetingName = true
|
||||
}
|
||||
|
||||
@@ -202,7 +263,8 @@
|
||||
}
|
||||
|
||||
function startEditMeetingTime() {
|
||||
meetingTimeInput = Math.floor((meeting?.timeLimit || 3600) / 60)
|
||||
originalMeetingTime = Math.floor((meeting?.timeLimit || 3600) / 60)
|
||||
meetingTimeInput = originalMeetingTime
|
||||
editingMeetingTime = true
|
||||
}
|
||||
|
||||
@@ -221,8 +283,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_JIRA_URL = defaultJiraUrl
|
||||
|
||||
function startEditMeetingJiraUrl() {
|
||||
meetingJiraUrlInput = meeting?.jiraUrl || ''
|
||||
originalMeetingJiraUrl = meeting?.jiraUrl || defaultJiraUrl
|
||||
meetingJiraUrlInput = originalMeetingJiraUrl
|
||||
editingMeetingJiraUrl = true
|
||||
}
|
||||
|
||||
@@ -272,11 +337,12 @@
|
||||
</div>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
||||
<h1 on:click={startEditMeetingName} class="editable-title">
|
||||
<h1 on:click={() => guardEdit(startEditMeetingName)} class="editable-title">
|
||||
{meeting?.name || 'Daily Standup'}
|
||||
<span class="edit-icon">✎</span>
|
||||
</h1>
|
||||
{/if}
|
||||
<div class="meeting-info-block">
|
||||
{#if editingMeetingTime}
|
||||
<div class="meeting-time-edit">
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
@@ -297,7 +363,7 @@
|
||||
</div>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
||||
<p on:click={startEditMeetingTime} class="editable-time">
|
||||
<p on:click={() => guardEdit(startEditMeetingTime)} class="editable-time">
|
||||
{$t('setup.totalTime')}: {formatTime(meeting?.timeLimit || 900)}
|
||||
<span class="edit-icon">✎</span>
|
||||
</p>
|
||||
@@ -320,13 +386,28 @@
|
||||
</div>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
||||
<p on:click={startEditMeetingJiraUrl} class="editable-jira">
|
||||
{$t('setup.jiraUrl')}: {meeting?.jiraUrl ? '🔗' : '—'}
|
||||
<p on:click={() => guardEdit(startEditMeetingJiraUrl)} class="editable-jira">
|
||||
{$t('setup.jiraUrl')}: {#if meeting?.jiraUrl}<span class="jira-url-value">{meeting.jiraUrl}</span>{:else}<span class="jira-default-label">(Default)</span>{/if}
|
||||
<span class="edit-icon">✎</span>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if confirmDialog}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||
<div class="confirm-overlay" on:click={confirmDialog.cancel}>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||
<div class="confirm-dialog" on:click|stopPropagation>
|
||||
<p class="confirm-text">Сохранить изменения?</p>
|
||||
<div class="confirm-actions">
|
||||
<button class="confirm-discard" on:click={confirmDialog.discard}>Отменить</button>
|
||||
<button class="confirm-save" on:click={confirmDialog.save}>Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="add-participant">
|
||||
<input
|
||||
type="text"
|
||||
@@ -384,9 +465,15 @@
|
||||
|
||||
<span class="name">{p.name}</span>
|
||||
<span class="time-limit">{Math.floor(p.timeLimit / 60)} {$t('setup.minutes')}</span>
|
||||
{#if p.jiraFilter}
|
||||
<span class="url-indicator" title="{meeting?.jiraUrl}&quickFilter={p.jiraFilter}">🔗</span>
|
||||
{/if}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="url-indicator"
|
||||
class:url-indicator--empty={!p.jiraFilter}
|
||||
title={p.jiraFilter ? `${meeting?.jiraUrl}&quickFilter=${p.jiraFilter}` : $t('participants.jiraFilterEmpty')}
|
||||
on:click|stopPropagation={() => startQuickFilterEdit(p)}
|
||||
>🔗</span>
|
||||
|
||||
<button class="edit" on:click={() => startEdit(p)} title="{$t('participants.edit')}">✎</button>
|
||||
<button class="remove" on:click={() => handleRemove(id)}>×</button>
|
||||
@@ -431,6 +518,30 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if quickFilterEditId !== null}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||
<div class="edit-modal-overlay" on:click={cancelQuickFilterEdit}>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||
<div class="edit-modal quick-filter-modal" on:click|stopPropagation>
|
||||
<h3>quickFilter ID</h3>
|
||||
<div class="edit-field">
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input id="quickFilterInput" type="text" bind:value={quickFilterInput}
|
||||
placeholder={$t('participants.jiraFilterPlaceholder')}
|
||||
autofocus
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') saveQuickFilterEdit()
|
||||
if (e.key === 'Escape') cancelQuickFilterEdit()
|
||||
}} />
|
||||
</div>
|
||||
<div class="edit-actions">
|
||||
<button class="cancel-btn" on:click={cancelQuickFilterEdit}>{$t('common.cancel')}</button>
|
||||
<button class="save-btn" on:click={saveQuickFilterEdit}>{$t('common.save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="summary">
|
||||
<span>{$t('setup.participants')}: {Object.values($attendance).filter(Boolean).length} / {participants.length}</span>
|
||||
<span>≈ {formatTime(selectedOrder.filter(id => $attendance[id]).reduce((acc, id) => acc + (getParticipant(id)?.timeLimit || 0), 0))}</span>
|
||||
@@ -450,11 +561,12 @@
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
color: #e0e0e0;
|
||||
display: block;
|
||||
}
|
||||
@@ -526,9 +638,11 @@
|
||||
|
||||
.header p.editable-time {
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.header p.editable-time:hover {
|
||||
@@ -591,10 +705,11 @@
|
||||
|
||||
.header p.editable-jira {
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
@@ -606,6 +721,32 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.meeting-info-block {
|
||||
margin: 12px 0 16px;
|
||||
border: 1px solid #3d4f61;
|
||||
border-radius: 10px;
|
||||
padding: 8px 16px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.jira-url-value {
|
||||
max-width: 280px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.jira-default-label {
|
||||
font-size: 11px;
|
||||
color: #4b5563;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.meeting-jira-edit {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@@ -795,9 +936,24 @@
|
||||
|
||||
.url-indicator {
|
||||
font-size: 12px;
|
||||
opacity: 0.7;
|
||||
cursor: default;
|
||||
opacity: 0.9;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
transition: opacity 0.15s;
|
||||
filter: sepia(1) saturate(3) hue-rotate(90deg);
|
||||
}
|
||||
|
||||
.url-indicator:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.url-indicator--empty {
|
||||
opacity: 0.2;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
.url-indicator--empty:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.edit {
|
||||
@@ -840,6 +996,61 @@
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.confirm-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 120px;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.confirm-dialog {
|
||||
background: #1e2d3d;
|
||||
border: 1px solid #374151;
|
||||
border-radius: 10px;
|
||||
padding: 16px 20px;
|
||||
min-width: 240px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.confirm-text {
|
||||
color: #e0e0e0;
|
||||
font-size: 14px;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
.confirm-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.confirm-discard {
|
||||
padding: 6px 14px;
|
||||
background: #374151;
|
||||
color: #9ca3af;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.confirm-save {
|
||||
padding: 6px 14px;
|
||||
background: #166534;
|
||||
color: #4ade80;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-modal {
|
||||
background: #232f3e;
|
||||
border-radius: 12px;
|
||||
@@ -848,6 +1059,10 @@
|
||||
max-width: 320px;
|
||||
}
|
||||
|
||||
.edit-modal.quick-filter-modal {
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.edit-modal h3 {
|
||||
margin: 0 0 16px 0;
|
||||
color: #e0e0e0;
|
||||
|
||||
@@ -23,11 +23,11 @@ export const translations = {
|
||||
deselectAll: 'Снять выбор',
|
||||
startMeeting: 'Начать собрание',
|
||||
speakerTime: 'Время на спикера',
|
||||
totalTime: 'Общее время',
|
||||
totalTime: 'Общее время собрания',
|
||||
minutes: 'мин',
|
||||
unlimited: 'Без ограничения',
|
||||
dragHint: 'перетащите для изменения порядка, ✓/✗ присутствие',
|
||||
jiraUrl: 'Jira URL собрания',
|
||||
jiraUrl: 'Jira Kanban URL',
|
||||
jiraUrlPlaceholder: 'https://jira.ncloudtech.ru/...',
|
||||
},
|
||||
|
||||
@@ -105,6 +105,7 @@ export const translations = {
|
||||
seconds: 'сек',
|
||||
defaultSpeakerTime: 'Время на спикера по умолчанию',
|
||||
defaultTotalTime: 'Общее время собрания (мин)',
|
||||
defaultJiraUrl: 'Jira URL Панели Kanban',
|
||||
theme: 'Тема оформления',
|
||||
themeDark: 'Тёмная',
|
||||
themeLight: 'Светлая',
|
||||
@@ -141,8 +142,9 @@ export const translations = {
|
||||
edit: 'Редактировать',
|
||||
delete: 'Удалить',
|
||||
name: 'Имя',
|
||||
jiraFilter: 'Jira Quick Filter',
|
||||
jiraFilter: 'Jira Kanban URL',
|
||||
jiraFilterPlaceholder: 'quickFilter ID (напр. 12345)',
|
||||
jiraFilterEmpty: 'Jira фильтр не задан — нажмите для настройки',
|
||||
stats: 'Статистика',
|
||||
avgSpeakTime: 'Среднее время выступления',
|
||||
totalMeetings: 'Всего собраний',
|
||||
@@ -200,11 +202,11 @@ export const translations = {
|
||||
deselectAll: 'Deselect All',
|
||||
startMeeting: 'Start Meeting',
|
||||
speakerTime: 'Speaker Time',
|
||||
totalTime: 'Total Time',
|
||||
totalTime: 'Total Meeting Time',
|
||||
minutes: 'min',
|
||||
unlimited: 'Unlimited',
|
||||
dragHint: 'drag to reorder, ✓/✗ attendance',
|
||||
jiraUrl: 'Meeting Jira URL',
|
||||
jiraUrl: 'Jira Kanban URL',
|
||||
jiraUrlPlaceholder: 'https://jira.ncloudtech.ru/...',
|
||||
},
|
||||
|
||||
@@ -282,6 +284,7 @@ export const translations = {
|
||||
seconds: 'sec',
|
||||
defaultSpeakerTime: 'Default Speaker Time',
|
||||
defaultTotalTime: 'Total meeting time (min)',
|
||||
defaultJiraUrl: 'Jira Kanban Board URL',
|
||||
theme: 'Theme',
|
||||
themeDark: 'Dark',
|
||||
themeLight: 'Light',
|
||||
@@ -318,8 +321,9 @@ export const translations = {
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
name: 'Name',
|
||||
jiraFilter: 'Jira Quick Filter',
|
||||
jiraFilter: 'Jira Kanban URL',
|
||||
jiraFilterPlaceholder: 'quickFilter ID (e.g. 12345)',
|
||||
jiraFilterEmpty: 'Jira filter not set — click to configure',
|
||||
stats: 'Statistics',
|
||||
avgSpeakTime: 'Avg Speaking Time',
|
||||
totalMeetings: 'Total Meetings',
|
||||
|
||||
@@ -333,6 +333,7 @@ export namespace models {
|
||||
windowFullHeight: boolean;
|
||||
windowX: number;
|
||||
windowY: number;
|
||||
defaultJiraUrl: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Settings(source);
|
||||
@@ -353,6 +354,7 @@ export namespace models {
|
||||
this.windowFullHeight = source["windowFullHeight"];
|
||||
this.windowX = source["windowX"];
|
||||
this.windowY = source["windowY"];
|
||||
this.defaultJiraUrl = source["defaultJiraUrl"];
|
||||
}
|
||||
}
|
||||
export class SpeakerInfo {
|
||||
|
||||
Reference in New Issue
Block a user