Skip to content

feat(create): add 'copy from existing' (clone) option to CreateComponent#3646

Open
sogladev wants to merge 17 commits intoazerothcore:masterfrom
sogladev:dev-copy-from
Open

feat(create): add 'copy from existing' (clone) option to CreateComponent#3646
sogladev wants to merge 17 commits intoazerothcore:masterfrom
sogladev:dev-copy-from

Conversation

@sogladev
Copy link
Member

@sogladev sogladev commented Dec 14, 2025

Changed proposed:

Add support for cloning an existing entity from the 'Create' card for multiple types.

I modified the tests for create.component.spec.ts. I'm not sure what other tests are needed for this.

FYI not an NX/Angular expert and I used AI tools to help draft this. Hopefully, nothing too bad in here

Details:

Adds allowCopy field to the CreateComponent <keira-create>, which is opt-in.

Handling is done by routing to a /clone route with a provided ID to copy from. This is similar to /select and /create that already exist. The /copy route displays a page with copy queries for the main table and related tables. After executing, the user is routed to the edit page.

After doing this for creatures, it was easy enough to copy and paste the handling for other types.

For gobjects and creatures, only the template-like tables are copied. SmartAI (TODO?), spawns or guid-specific stuff is not copied.

Issues

UI

UI Screenshots

keira_38_1

keira_3

keira_4

[[copilot summary below]]

This pull request adds support for "copy" routes and features across multiple entity types in the Keira app, allowing users to duplicate existing entries. It also introduces new internationalized strings related to the copy functionality in all supported languages.

Key changes include:

Routing and Feature Enhancements:

  • Added new "copy" routes for various entities (e.g., Creature, Quest, Gameobject, Item, Spell, Gossip, GameTele, FishingLoot, MailLoot, ReferenceLoot, PageText, NpcText, AcoreString) in routes.ts, each guarded by the appropriate handler service and linked to the corresponding CopyComponent. This enables users to copy existing records for these entities. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
  • Updated imports in routes.ts to include all new CopyComponent classes for the affected features. [1] [2] [3] [4] [5] [6]

Internationalization (i18n):

  • Added new strings for copy-related UI elements (such as "Copy from existing", "Copy Entry SQL", "Execute", "Continue to Editor", etc.) to all supported language files (en.json, de.json, es.json, fr.json, el.json, it.json). This ensures the new copy functionality is fully localized. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

These changes collectively introduce and localize the experimental ability to copy existing entries for a wide range of entities within the Keira application, improving user productivity and data management.

@sogladev sogladev marked this pull request as draft January 20, 2026 19:51
@sogladev sogladev marked this pull request as ready for review January 20, 2026 20:29
[newId]="newId"
[relatedTables]="relatedTables"
/>
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a lot of duplication code, we could conside to use only one file.html for all 🤔 , are they always the same?

}
get allowCopy(): boolean {
return this._allowCopy;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly necessary, I could refactor it a bit later, but I would use signals for this if possible

id="method-blank"
value="blank"
[(ngModel)]="creationMethod"
(change)="onCreationMethodChange()"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we prefer ReactiveFormsModule instead of ngModel and (change), if possible

@Helias
Copy link
Member

Helias commented Jan 20, 2026

It's a big job, it's fantastic 💯 , I left some comments

sogladev and others added 2 commits January 24, 2026 17:03
remove default

specify imports

remove some imports

move select handler logic to shared handler

move text to translation file

remove 'public'

add 'protected'

refactor @input to signal, define interface

remove 'standalone'
@sogladev
Copy link
Member Author

Thanks for the review, I updated it with your suggestions @Helias

I skipped refactoring libs/shared/base-editor-components/src/create/create.component.html to use `ReactiveFormsModule.'

I also did have trouble with abstracting spell-loot-copy.component.html and other *-copy.component.html to some kind of shared component.html. But, I wasn't sure how to pass relatedTables and others to this new component

  templateUrl: '../../../../../libs/shared/base-editor-components/src/copy-output/copy-output.component.html',
  standalone: true,

@Helias
Copy link
Member

Helias commented Jan 25, 2026

pipeline is failing

@sogladev
Copy link
Member Author

test coverage issue. working on it

Comment on lines +13 to +29
type CopyMode = 'RAW' | 'ALL';

interface RelatedTable {
tableName: string;
idField: string;
copyMode?: CopyMode;
columns?: string[];
}

interface RelatedTableState {
tableName: string;
idField: string;
count: number;
included: boolean;
copyMode: CopyMode;
columns?: string[];
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to avoid too big Component classes, these types could be moved to a separate copy-output.model.ts file

// Navigate to the editor for the newly created entry
this.handlerService()!.select(false, this.newId());
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bonus: maybe some of the logic of these methods can be moved to some pure functions or to a service? but not mandatory given that it's not always really doable

Comment on lines +17 to +20
constructor(fixture: ComponentFixture<CreateComponent<TableRow>>) {
super(fixture);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to override the constructor to just call super

Suggested change
constructor(fixture: ComponentFixture<CreateComponent<TableRow>>) {
super(fixture);
}

Comment on lines +42 to +44
let component: CreateComponent<any>;
let fixture: ComponentFixture<CreateComponent<any>>;
let page: CreateComponentPage;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid sharing non-immutable variables across tests. Better to have those as const, created inside a setup() function that returns them. Avoid initializing them inside the beforeEach

See how other tests are made. There are still some leftovers that do not respect this pattern, which I'm fixing in another PR.

Comment on lines +61 to +70
fixture = TestBed.createComponent(CreateComponent);
component = fixture.componentInstance;
// Provide required inputs
component.entityTable = 'test';
component.entityIdField = 'id';
component.customStartingId = 1;
component.queryService = fakeQueryService;
component.handlerService = fakeHandlerService;
fixture.detectChanges();
page = new CreateComponentPage(fixture);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be moved inside a setup function, see comment above

protected checkSourceId(): void {
if (!this.sourceIdModel) {
this.isSourceIdValid = false;
this.changeDetectorRef.markForCheck();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to just use Signals whenever a non-immutable variable is used in the template. This way one does not need to call markForCheck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] - Ability to clone existing entity Feature Request: Clone/Copy Options Suggestion: Data replication

4 participants