From 5552dc5e672e3ac90c9b374e02641c81fa6d65e6 Mon Sep 17 00:00:00 2001 From: Nils Jacobsen Date: Thu, 21 Mar 2024 14:50:13 +0100 Subject: [PATCH] feat: update api - removed dynamic imports to access schemas - removed events (for now, let's see if we like the business logic in the component) --- .../settings-component/src/mock/project.ts | 106 +++++++- .../src/stories/inlang-settings.stories.ts | 8 +- .../src/stories/inlang-settings.ts | 241 +++++++++--------- .../{simple-input.ts => general-input.ts} | 9 +- .../object/lint-rule-level-object-input.ts | 56 ++-- 5 files changed, 249 insertions(+), 171 deletions(-) rename inlang/source-code/settings-component/src/stories/input-fields/{simple-input.ts => general-input.ts} (91%) diff --git a/inlang/source-code/settings-component/src/mock/project.ts b/inlang/source-code/settings-component/src/mock/project.ts index 175585ef0b..87c0b04345 100644 --- a/inlang/source-code/settings-component/src/mock/project.ts +++ b/inlang/source-code/settings-component/src/mock/project.ts @@ -1,7 +1,12 @@ -export let mockSettings = { +import type { InlangProject } from "@inlang/sdk" + +export let mockSettings: ReturnType = { $schema: "https://inlang.com/schema/project-settings", sourceLanguageTag: "en", languageTags: ["en", "es", "fr", "pt-br", "ru", "zh-cn"], + messageLintRuleLevels: { + "messageLintRule.inlang.identicalPattern": "error", + }, modules: [ "https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@4/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js", @@ -42,32 +47,123 @@ export const mockProject = { displayName: "i18next", description: "i18next", module: "https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@4/dist/index.js", + settingsSchema: { + type: "object", + properties: { + pathPattern: { + anyOf: [ + { + pattern: "^(\\./|\\../|/)[^*]*\\{languageTag\\}[^*]*\\.json", + description: "The pathPattern must contain `{languageTag}` and end with `.json`.", + examples: [ + "./{languageTag}/file.json", + "../folder/{languageTag}/file.json", + "./{languageTag}.json", + ], + type: "string", + }, + { + type: "object", + patternProperties: { + "^[^.]+$": { + pattern: "^(\\./|\\../|/)[^*]*\\{languageTag\\}[^*]*\\.json", + description: + "The pathPattern must contain `{languageTag}` and end with `.json`.", + examples: [ + "./{languageTag}/file.json", + "../folder/{languageTag}/file.json", + "./{languageTag}.json", + ], + type: "string", + }, + }, + }, + ], + }, + variableReferencePattern: { + type: "array", + items: { + type: "string", + }, + }, + sourceLanguageFilePath: { + anyOf: [ + { + pattern: "^(\\./|\\../|/)[^*]*\\{languageTag\\}[^*]*\\.json", + description: "The pathPattern must contain `{languageTag}` and end with `.json`.", + examples: [ + "./{languageTag}/file.json", + "../folder/{languageTag}/file.json", + "./{languageTag}.json", + ], + type: "string", + }, + { + type: "object", + patternProperties: { + "^[^.]+$": { + pattern: "^(\\./|\\../|/)[^*]*\\{languageTag\\}[^*]*\\.json", + description: + "The pathPattern must contain `{languageTag}` and end with `.json`.", + examples: [ + "./{languageTag}/file.json", + "../folder/{languageTag}/file.json", + "./{languageTag}.json", + ], + type: "string", + }, + }, + }, + ], + }, + ignore: { + type: "array", + items: { + type: "string", + }, + }, + }, + required: ["pathPattern"], + }, }, ], messageLintRules: () => [ { - id: "message-lint-rule-empty-pattern", + id: "messageLintRule.inlang.emptyPattern", displayName: "Empty Pattern", description: "Empty Pattern", module: "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js", }, { - id: "message-lint-rule-identical-pattern", + id: "messageLintRule.inlang.identicalPattern", displayName: "Identical Pattern", description: "Identical Pattern", module: "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@latest/dist/index.js", + settingsSchema: { + type: "object", + properties: { + ignore: { + type: "array", + items: { + pattern: "[^*]", + description: "All items in the array need quotaion marks at the end and beginning", + type: "string", + }, + }, + }, + }, }, { - id: "message-lint-rule-missing-translation", + id: "messageLintRule.inlang.missingTranslation", displayName: "Missing Translation", description: "Missing Translation", module: "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js", }, { - id: "message-lint-rule-without-source", + id: "messageLintRule.inlang.messageWithoutSource", displayName: "Without Source", description: "Without Source", module: diff --git a/inlang/source-code/settings-component/src/stories/inlang-settings.stories.ts b/inlang/source-code/settings-component/src/stories/inlang-settings.stories.ts index 3f9b795a8f..5e7cf4b59b 100644 --- a/inlang/source-code/settings-component/src/stories/inlang-settings.stories.ts +++ b/inlang/source-code/settings-component/src/stories/inlang-settings.stories.ts @@ -12,11 +12,5 @@ const meta: Meta = { export default meta export const Default: StoryObj = { - render: () => - html` - console.info("save", settings)} - > - `, + render: () => html` `, } diff --git a/inlang/source-code/settings-component/src/stories/inlang-settings.ts b/inlang/source-code/settings-component/src/stories/inlang-settings.ts index 060911d7c5..170f638e81 100644 --- a/inlang/source-code/settings-component/src/stories/inlang-settings.ts +++ b/inlang/source-code/settings-component/src/stories/inlang-settings.ts @@ -1,10 +1,15 @@ import { html, LitElement, css } from "lit" import { customElement, property, state } from "lit/decorators.js" import { baseStyling } from "../styling/base.js" -import { type InlangModule, ProjectSettings, type InlangProject } from "@inlang/sdk" -import { Task } from "@lit/task" +import { + type InlangModule, + ProjectSettings, + type InlangProject, + type InstalledPlugin, + type InstalledMessageLintRule, +} from "@inlang/sdk" -import "./input-fields/simple-input.js" +import "./input-fields/general-input.js" import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js" import SLOption from "@shoelace-style/shoelace/dist/components/option/option.component.js" @@ -81,7 +86,7 @@ export default class InlangSettings extends LitElement { project: InlangProject = {} as InlangProject @state() - private _newProject: ProjectSettings | undefined = undefined + private _newSettings: ProjectSettings | undefined = undefined @state() private _unsavedChanges: boolean = false @@ -90,7 +95,7 @@ export default class InlangSettings extends LitElement { await this.updateComplete if (this.project?.settings()) { - this._newProject = JSON.parse(JSON.stringify(this.project.settings())) + this._newSettings = JSON.parse(JSON.stringify(this.project.settings())) } } @@ -101,21 +106,21 @@ export default class InlangSettings extends LitElement { moduleId?: InlangModule["default"]["id"] ) => { //update state object - if (this._newProject && moduleId) { - this._newProject = { - ...this._newProject, + if (this._newSettings && moduleId) { + this._newSettings = { + ...this._newSettings, [moduleId]: { - ...this._newProject[moduleId], + ...this._newSettings[moduleId], [property]: value, }, } - } else if (this._newProject) { - this._newProject = { - ...this._newProject, + } else if (this._newSettings) { + this._newSettings = { + ...this._newSettings, [property]: value, } } - if (JSON.stringify(this.project?.settings()) !== JSON.stringify(this._newProject)) { + if (JSON.stringify(this.project?.settings()) !== JSON.stringify(this._newSettings)) { this._unsavedChanges = true } else { this._unsavedChanges = false @@ -124,136 +129,120 @@ export default class InlangSettings extends LitElement { _revertChanges = () => { if (this.project?.settings()) { - this._newProject = JSON.parse(JSON.stringify(this.project?.settings())) + this._newSettings = JSON.parse(JSON.stringify(this.project?.settings())) } this._unsavedChanges = false } _saveChanges = () => { - if (this._newProject) { - this.project?.setSettings(this._newProject) + if (this._newSettings) { + this.project?.setSettings(this._newSettings) } this._unsavedChanges = false } - private _projectProperties = new Task(this, { - task: async ([project]) => { - const _project = project - if (!_project) throw new Error("No inlang project") - if (!_project.settings()) throw new Error("No inlang project") - - const generalSchema: Record< - InlangModule["default"]["id"] | "internal", - { meta?: InlangModule["default"]; schema?: Record> } - > = { internal: { schema: ProjectSettings.allOf[0] } } + private get _projectSettingProperties(): Record< + InlangModule["default"]["id"] | "internal", + { + meta?: InstalledPlugin | InstalledMessageLintRule + schema?: Record> + } + > { + const _project = this.project + if (!_project) throw new Error("No inlang project") + if (!_project.settings()) throw new Error("No inlang project settings") + + const generalSchema: Record< + InlangModule["default"]["id"] | "internal", + { + meta?: InstalledPlugin | InstalledMessageLintRule + schema?: Record> + } + > = { internal: { schema: ProjectSettings.allOf[0] } } - for (const plugin of _project.installed.plugins()) { - try { - const importedPlugin = await import(plugin.module) - if (importedPlugin.default) { - generalSchema[importedPlugin.default.id] = { - schema: importedPlugin.default.settingsSchema, - meta: importedPlugin.default, - } - } - } catch (e) { - console.error(e) + for (const plugin of _project.installed.plugins()) { + if (plugin.settingsSchema) { + generalSchema[plugin.id] = { + schema: plugin.settingsSchema, + meta: plugin, } } - for (const lintRule of _project.installed.messageLintRules()) { - try { - const importedLintRule = await import(lintRule.module) - if (importedLintRule.default) { - generalSchema[importedLintRule.default.id] = { - schema: importedLintRule.default.settingsSchema, - meta: importedLintRule.default, - } - } - } catch (e) { - console.error(e) + } + for (const lintRule of _project.installed.messageLintRules()) { + if (lintRule.settingsSchema) { + generalSchema[lintRule.id] = { + schema: lintRule.settingsSchema, + meta: lintRule, } } + } - return generalSchema - }, - args: () => [this.project], - }) + return generalSchema + } override render() { - return this._projectProperties.render({ - pending: () => html`
Loading...
`, - complete: (properties) => - html`
- ${Object.entries(properties).map(([key, value]) => { - return value.schema?.properties && this._newProject - ? html`
-

- ${(value.meta as { displayName?: { en: string } })?.displayName?.en || key} -

- ${Object.entries(value.schema.properties).map(([property, schema]) => { - if ( - property === "$schema" || - property === "modules" || - property === "experimental" - ) - return undefined - return key === "internal" - ? html` - - ` - : html` - - ` - })} -
` - : undefined - })} - ${this._unsavedChanges - ? html`
-
-

Attention, you have unsaved changes.

-
- { - this._revertChanges() - }} - varaint="default" - > - Cancel - - { - this._saveChanges() - }} - variant="primary" - > - Save Changes - -
-
-
` - : html``} -
`, - - error: (e) => html`

Error: ${e}

`, - }) + return html`
+ ${Object.entries(this._projectSettingProperties).map(([key, value]) => { + return value.schema?.properties && this._newSettings + ? html`
+

${value.meta?.displayName || key}

+ ${Object.entries(value.schema.properties).map(([property, schema]) => { + if (property === "$schema" || property === "modules" || property === "experimental") + return undefined + return key === "internal" + ? html` + + ` + : html` + + ` + })} +
` + : undefined + })} + ${this._unsavedChanges + ? html`
+
+

Attention, you have unsaved changes.

+
+ { + this._revertChanges() + }} + varaint="default" + > + Cancel + + { + this._saveChanges() + }} + variant="primary" + > + Save Changes + +
+
+
` + : html``} +
` } } diff --git a/inlang/source-code/settings-component/src/stories/input-fields/simple-input.ts b/inlang/source-code/settings-component/src/stories/input-fields/general-input.ts similarity index 91% rename from inlang/source-code/settings-component/src/stories/input-fields/simple-input.ts rename to inlang/source-code/settings-component/src/stories/input-fields/general-input.ts index 46cca06f90..2885ee01f2 100644 --- a/inlang/source-code/settings-component/src/stories/input-fields/simple-input.ts +++ b/inlang/source-code/settings-component/src/stories/input-fields/general-input.ts @@ -5,8 +5,9 @@ import "./string/string-input.js" import "./array/array-input.js" import "./object/object-input.js" import "./union/path-pattern-input.js" -@customElement("simple-input") -export class SimpleInput extends LitElement { +import type { InstalledMessageLintRule, InstalledPlugin } from "@inlang/sdk" +@customElement("general-input") +export class GeneralInput extends LitElement { static override styles = baseStyling @property() @@ -16,7 +17,7 @@ export class SimpleInput extends LitElement { moduleId?: string @property() - modules?: string + modules?: Array @property() value: string = "" @@ -98,6 +99,6 @@ export class SimpleInput extends LitElement { // add types declare global { interface HTMLElementTagNameMap { - "simple-input": SimpleInput + "general-input": GeneralInput } } diff --git a/inlang/source-code/settings-component/src/stories/input-fields/object/lint-rule-level-object-input.ts b/inlang/source-code/settings-component/src/stories/input-fields/object/lint-rule-level-object-input.ts index 7c6d5bb05d..f6f44c5468 100644 --- a/inlang/source-code/settings-component/src/stories/input-fields/object/lint-rule-level-object-input.ts +++ b/inlang/source-code/settings-component/src/stories/input-fields/object/lint-rule-level-object-input.ts @@ -1,7 +1,7 @@ import { css, html, LitElement } from "lit" import { customElement, property } from "lit/decorators.js" import { baseStyling } from "../../../styling/base.js" -import { Plugin, MessageLintRule, InlangModule } from "@inlang/sdk" +import { InlangModule, type InstalledMessageLintRule, type InstalledPlugin } from "@inlang/sdk" @customElement("lint-rule-level-object-input") export class LintRuleLevelObjectInput extends LitElement { @@ -42,7 +42,7 @@ export class LintRuleLevelObjectInput extends LitElement { moduleId?: string @property() - modules?: object + modules?: Array @property() value: Record = {} @@ -86,33 +86,31 @@ export class LintRuleLevelObjectInput extends LitElement { ${this._description && html`

${this._description}

`}
${this.modules && - Object.entries(this.modules).map( - ([key, module]: [string, Record>]) => { - return key !== "internal" && key.split(".")[0] !== "plugin" - ? html`
- { - this.handleUpdate( - key as `plugin.${string}.${string}` | `messageLintRule.${string}.${string}`, - (e.target as HTMLInputElement).value - ) - }} - > - ${this._valueOptions?.map((option) => { - return html` - ${option.const} - ` - })} - -

${(module.meta as Plugin | MessageLintRule | undefined)?.id}

-
` - : undefined - } - )} + this.modules.map((module) => { + return module.id.split(".")[0] !== "plugin" + ? html`
+ { + this.handleUpdate( + module.id as `messageLintRule.${string}.${string}`, + (e.target as HTMLInputElement).value + ) + }} + > + ${this._valueOptions?.map((option) => { + return html` + ${option.const} + ` + })} + +

${module.displayName}

+
` + : undefined + })}
` }