import '@material/web/button/filled-button.js' import '@material/web/button/text-button.js' import '@material/web/textfield/filled-text-field.js' import { css, html } from 'lit' import { customElement, state } from 'lit/decorators.js' import { client, PageView, navigate } from '@things-factory/shell/client' import gql from 'graphql-tag' @customElement('label-studio-project-create') export class LabelStudioProjectCreate extends PageView { static styles = [ css` :host { display: flex; flex-direction: column; padding: 20px; max-width: 800px; margin: 0 auto; } h2 { margin: 0 0 20px 0; color: var(--md-sys-color-on-surface); } .form-field { margin-bottom: 20px; } .form-field label { display: block; margin-bottom: 8px; color: var(--md-sys-color-on-surface); font-weight: 500; } md-filled-text-field { width: 100%; } textarea { width: 100%; min-height: 200px; padding: 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 4px; font-family: monospace; font-size: 14px; resize: vertical; } .actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; } .template-examples { margin-top: 20px; padding: 15px; background: var(--md-sys-color-surface-variant); border-radius: 8px; } .template-examples h4 { margin: 0 0 10px 0; } .template-btn { margin: 5px; } .error { color: var(--md-sys-color-error); margin: 10px 0; } ` ] @state() title: string = '' @state() description: string = '' @state() labelConfig: string = '' @state() saving: boolean = false @state() error: string = '' render() { return html`

Create Label Studio Project

(this.title = e.target.value)} placeholder="Enter project title" >
(this.description = e.target.value)} placeholder="Enter project description" >

Quick Templates

this.useTemplate('text-classification')}> Text Classification this.useTemplate('image-classification')}> Image Classification this.useTemplate('ner')}> Named Entity Recognition
${this.error ? html`
${this.error}
` : ''}
Cancel ${this.saving ? 'Creating...' : 'Create Project'}
` } useTemplate(type: string) { const templates = { 'text-classification': ` `, 'image-classification': ` `, ner: ` ` } this.labelConfig = templates[type] || '' } async save() { if (!this.title || !this.labelConfig) { this.error = 'Title and Label Configuration are required' return } try { this.saving = true this.error = '' const response = await client.mutate({ mutation: gql` mutation CreateProject($input: CreateProjectInput!) { createLabelStudioProject(input: $input) { id title } } `, variables: { input: { title: this.title, description: this.description || undefined, labelConfig: this.labelConfig } } }) const project = response.data.createLabelStudioProject // Navigate to project list navigate('label-studio-project-list') } catch (error: any) { console.error('Failed to create project:', error) this.error = error.message || 'Failed to create project' } finally { this.saving = false } } cancel() { navigate('label-studio-project-list') } }