import '@material/web/icon/icon.js'
import '@material/web/chips/assist-chip.js'
import '@operato/data-grist/ox-empty-note.js'
import gql from 'graphql-tag'
import { css, html, LitElement } from 'lit'
import { customElement, property, state } from 'lit/decorators.js'
import { i18next } from '@operato/i18n'
import { client } from '@operato/graphql'
import { notify } from '@operato/layout'
import { OxPrompt } from '@operato/popup/ox-prompt.js'
import { ScrollbarStyles } from '@operato/styles'
/**
* 시나리오 버전 히스토리 패널.
*
* - 릴리즈된 버전 목록(버전번호·코멘트·작성자·시각)
* - 각 버전을 현재 draft 와 비교하는 diff 뷰
* - 과거 버전을 현재 draft 로 복사(revert)
*
* board-ui 의 board-versions 를 시나리오(스텝 배열 diff)에 맞춰 확장한 형태.
*/
@customElement('scenario-versions')
export class ScenarioVersions extends LitElement {
static styles = [
ScrollbarStyles,
css`
:host {
display: flex;
flex-direction: column;
overflow: auto;
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
font: var(--label-font);
padding: var(--spacing-medium, 12px);
gap: var(--spacing-medium, 12px);
}
div[card] {
position: relative;
border: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.12));
border-radius: var(--border-radius, 6px);
padding: var(--spacing-medium, 12px);
text-align: start;
}
div[head] {
display: flex;
align-items: center;
gap: var(--spacing-small, 6px);
}
div[head] [ver] {
font: var(--subtitle-font, bold 14px sans-serif);
color: var(--md-sys-color-primary);
display: inline-flex;
align-items: center;
gap: 3px;
}
div[head] [meta] {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 5px;
opacity: 0.75;
font-size: var(--fontsize-small, 12px);
}
div[comment] {
margin-top: 6px;
white-space: pre-wrap;
color: var(--md-sys-color-on-surface-variant, inherit);
}
div[actions] {
display: flex;
gap: var(--spacing-small, 6px);
margin-top: 8px;
}
md-icon {
font-size: var(--fontsize-large, 18px);
vertical-align: middle;
}
button {
cursor: pointer;
border: 1px solid var(--md-sys-color-outline, rgba(0, 0, 0, 0.2));
background: var(--md-sys-color-surface);
color: inherit;
border-radius: var(--border-radius, 6px);
padding: 4px 10px;
display: inline-flex;
align-items: center;
gap: 4px;
font: inherit;
}
button[primary] {
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
border-color: transparent;
}
div[diff] {
margin-top: 8px;
border-top: 1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.12));
padding-top: 8px;
font-size: var(--fontsize-small, 12px);
}
div[diff] [group] {
font-weight: bold;
margin: 4px 0 2px;
}
[change] {
display: block;
padding: 1px 0;
}
[change][added] {
color: var(--md-sys-color-primary, green);
}
[change][removed] {
color: var(--md-sys-color-error, #b00020);
text-decoration: line-through;
opacity: 0.8;
}
[change][modified] {
color: var(--status-warning-color, #b26a00);
}
[change] small {
opacity: 0.7;
}
ox-empty-note {
padding: 24px;
opacity: 0.7;
}
`
]
@property({ type: String }) scenarioId?: string
@property({ type: String }) scenarioName?: string
/** revert(과거→draft 복사) 성공 시 호출 — 목록 자동 갱신용 콜백(속성 바인딩이라 팝업 경계에서도 확실히 동작). */
@property({ attribute: false }) onReverted?: () => void
@state() versions: any[] = []
/** version → diff 결과(펼쳐진 경우만 존재) */
@state() diffs: { [version: number]: any } = {}
render() {
return html`
${this.versions.length == 0
? /* 빈 상태는 프레임워크 공통 부품(ox-empty-note) 사용 */
html`