Make version tags mandatory again.
This commit is contained in:
parent
d0b3be1749
commit
4bfabb9469
94 changed files with 405 additions and 489 deletions
|
|
@ -2776,40 +2776,12 @@ sub www_addSave {
|
|||
return $self->session->style->userStyle($i18n->get("over max assets")) if ($self->session->config->get("maximumAssets") <= $count);
|
||||
}
|
||||
|
||||
# Determine what version tag we should use
|
||||
my $autoCommitId = $self->getAutoCommitWorkflowId();
|
||||
|
||||
my ($workingTag, $oldWorking);
|
||||
if ( $autoCommitId ) {
|
||||
$workingTag
|
||||
= WebGUI::VersionTag->create( $session, {
|
||||
groupToUse => '12', # Turn Admin On (for lack of something better)
|
||||
workflowId => $autoCommitId,
|
||||
} );
|
||||
}
|
||||
else {
|
||||
my $parentAsset;
|
||||
if ( not defined( $parentAsset = $self->getParent ) ) {
|
||||
$parentAsset = WebGUI::Asset->newPending( $session, $self->parentId );
|
||||
}
|
||||
if ( $parentAsset->hasBeenCommitted ) {
|
||||
$workingTag = WebGUI::VersionTag->getWorking( $session );
|
||||
}
|
||||
else {
|
||||
$oldWorking = WebGUI::VersionTag->getWorking($session, 'noCreate');
|
||||
$workingTag = WebGUI::VersionTag->new( $session, $parentAsset->tagId );
|
||||
$workingTag->setWorking();
|
||||
}
|
||||
}
|
||||
|
||||
# Add the new asset
|
||||
my $object;
|
||||
my $className = $form->process('className','className') || $form->process('class','className');
|
||||
$object = $self->addChild({
|
||||
className => $className,
|
||||
revisedBy => $session->user->userId,
|
||||
tagId => $workingTag->getId,
|
||||
status => "pending",
|
||||
});
|
||||
if ( !defined $object ) {
|
||||
my $url = $session->url->page;
|
||||
|
|
@ -2819,11 +2791,6 @@ sub www_addSave {
|
|||
$object->{_parent} = $self;
|
||||
$object->url(undef);
|
||||
|
||||
# More version tag stuff
|
||||
$object->setVersionLock;
|
||||
$object->setAutoCommitTag($workingTag) if (defined $autoCommitId);
|
||||
$oldWorking->setWorking if $oldWorking;
|
||||
|
||||
# Process properties from form post
|
||||
my $errors = $object->processEditForm;
|
||||
if (ref $errors eq 'ARRAY') {
|
||||
|
|
@ -2924,43 +2891,8 @@ sub www_editSave {
|
|||
return $session->privilege->locked() unless $self->canEditIfLocked;
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
|
||||
# Determine what version tag we should use
|
||||
my $autoCommitId = $self->getAutoCommitWorkflowId();
|
||||
|
||||
my ($workingTag, $oldWorking);
|
||||
if ( $autoCommitId ) {
|
||||
$workingTag
|
||||
= WebGUI::VersionTag->create( $session, {
|
||||
groupToUse => '12', # Turn Admin On (for lack of something better)
|
||||
workflowId => $autoCommitId,
|
||||
} );
|
||||
}
|
||||
else {
|
||||
my $parentAsset;
|
||||
if ( not defined( $parentAsset = $self->getParent ) ) {
|
||||
$parentAsset = WebGUI::Asset->newPending( $session, $self->parentId );
|
||||
}
|
||||
if ( $parentAsset->hasBeenCommitted ) {
|
||||
$workingTag = WebGUI::VersionTag->getWorking( $session );
|
||||
}
|
||||
else {
|
||||
$oldWorking = WebGUI::VersionTag->getWorking($session, 'noCreate');
|
||||
$workingTag = WebGUI::VersionTag->new( $session, $parentAsset->tagId );
|
||||
$workingTag->setWorking();
|
||||
}
|
||||
}
|
||||
|
||||
# Add the new revision
|
||||
my $object = $self->addRevision({
|
||||
revisedBy => $session->user->userId,
|
||||
tagId => $workingTag->getId,
|
||||
status => "pending",
|
||||
});
|
||||
|
||||
# More version tag stuff
|
||||
$object->setVersionLock;
|
||||
$object->setAutoCommitTag($workingTag) if (defined $autoCommitId);
|
||||
$oldWorking->setWorking if $oldWorking;
|
||||
my $object = $self->addRevision();
|
||||
|
||||
# Process properties from form post
|
||||
my $errors = $object->processEditForm;
|
||||
|
|
|
|||
|
|
@ -98,11 +98,14 @@ property seatsAvailable => (
|
|||
property startDate => (
|
||||
noFormPost => 1,
|
||||
fieldType => "dateTime",
|
||||
default => '',
|
||||
builder => '_default_startDate',
|
||||
label => [ "add/edit event start date", 'Asset_EMSSubmission' ],
|
||||
hoverHelp => [ "add/edit event start date help", 'Asset_EMSSubmission' ],
|
||||
autoGenerate => 0,
|
||||
);
|
||||
sub _default_startDate {
|
||||
return WebGUI::DateTime->new()->toMysql;
|
||||
}
|
||||
property duration => (
|
||||
tab => "properties",
|
||||
fieldType => "float",
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ sub addSubmission {
|
|||
$newParams->{submissionId} = $self->ems->getNextSubmissionId;
|
||||
my $newAsset = $self->addChild($newParams);
|
||||
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session, { override => 1, allowComments => 0 });
|
||||
$self = $self->cloneFromDb;
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ sub disqualifyAsLastPost {
|
|||
$thread->update({ lastPostId => $secondary_post->getId, lastPostDate => $secondary_post->get('creationDate'), });
|
||||
}
|
||||
else {
|
||||
$thread->update({ lastPostId => '', lastPostDate => '', });
|
||||
$thread->update({ lastPostId => '', lastPostDate => 0 });
|
||||
}
|
||||
}
|
||||
my $cs = $thread->getParent;
|
||||
|
|
@ -359,7 +359,7 @@ sub disqualifyAsLastPost {
|
|||
$cs->update({ lastPostId => $secondary_post->getId, lastPostDate => $secondary_post->get('creationDate'), });
|
||||
}
|
||||
else {
|
||||
$cs->update({ lastPostId => '', lastPostDate => '', });
|
||||
$cs->update({ lastPostId => '', lastPostDate => 0 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ property lastPostId => (
|
|||
property lastPostDate => (
|
||||
noFormPost => 1,
|
||||
fieldType => "dateTime",
|
||||
default => undef,
|
||||
default => 0,
|
||||
);
|
||||
property karma => (
|
||||
noFormPost => 1,
|
||||
|
|
|
|||
|
|
@ -620,13 +620,13 @@ sub www_createSubscriptionCodeBatch {
|
|||
name => 'name',
|
||||
label => $i18n->get('batch name'),
|
||||
hoverHelp => $i18n->get('batch name description'),
|
||||
value => $session->form->process('name'),
|
||||
value => $session->form->process('name') || '',
|
||||
);
|
||||
$f->addField( "textarea",
|
||||
name => 'description',
|
||||
label => $i18n->get('batch description'),
|
||||
hoverHelp => $i18n->get('batch description description'),
|
||||
value => $session->form->process("description"),
|
||||
value => $session->form->process("description") || '',
|
||||
);
|
||||
$f->addField( "submit", name => "send" );
|
||||
|
||||
|
|
|
|||
|
|
@ -1379,7 +1379,7 @@ around groupIdView => sub {
|
|||
my $oldValue = $self->$orig;
|
||||
my $return = $self->$orig(@_);
|
||||
# Update the subscription group so if they can't see the collab, they don't get e-mailed
|
||||
if ( $newValue && $newValue != $oldValue ) {
|
||||
if ( $newValue && $newValue ne $oldValue ) {
|
||||
my $instance_data = {
|
||||
workflowId => 'xR-_GRRbjBojgLsFx3dEMA',
|
||||
className => 'WebGUI::Asset',
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ use WebGUI::Asset::Wobject::Folder;
|
|||
use WebGUI::Paginator;
|
||||
use WebGUI::Keyword;
|
||||
use WebGUI::Search;
|
||||
use WebGUI::VersionTag;
|
||||
|
||||
use File::Path;
|
||||
|
||||
|
|
@ -302,7 +303,20 @@ sub getFolder {
|
|||
my $folder = eval { WebGUI::Asset->newByUrl($session, $folderUrl); };
|
||||
return $folder if !Exception::Class->caught();
|
||||
|
||||
##The requested folder doesn't exist. Make it.
|
||||
##The requested folder doesn't exist. Make it and autocommit it.
|
||||
|
||||
##For a fully automatic commit, save the current tag, create a new one
|
||||
##with the commit without approval workflow, commit it, then restore
|
||||
##the original if it exists
|
||||
my ($oldVersionTag, $newVersionTag);
|
||||
$oldVersionTag = WebGUI::VersionTag->getWorking($session, 'noCreate');
|
||||
|
||||
if ($self->hasBeenCommitted) {
|
||||
$newVersionTag = WebGUI::VersionTag->create($session, { workflowId => 'pbworkflow00000000003', });
|
||||
$newVersionTag->setWorking;
|
||||
$newVersionTag->set({ name => 'Adding folder '. $folderName. ' to archive '. $self->getUrl});
|
||||
}
|
||||
|
||||
|
||||
##Call SUPER because my addChild calls getFolder
|
||||
$folder = $self->addChild({
|
||||
|
|
@ -313,6 +327,9 @@ sub getFolder {
|
|||
isHidden => 1,
|
||||
styleTemplateId => $self->styleTemplateId,
|
||||
});
|
||||
$newVersionTag->commit() if $newVersionTag;
|
||||
##Restore the old one, if it exists
|
||||
$oldVersionTag->setWorking() if $oldVersionTag;
|
||||
|
||||
##Get a new version of the asset from the db with the correct state
|
||||
$folder = $folder->cloneFromDb();
|
||||
|
|
|
|||
|
|
@ -72,18 +72,15 @@ sub copy {
|
|||
my $tree = WebGUI::ProgressTree->new($session, [ $asset->getId ] );
|
||||
$process->update(sub { $tree->json });
|
||||
my $newAsset = $asset->duplicate({ state => "clipboard" });
|
||||
|
||||
# If we aren't committing, add to a tag
|
||||
if ( !$args->{commit} ) {
|
||||
$newAsset->update({
|
||||
status => "pending",
|
||||
tagId => WebGUI::VersionTag->getWorking( $session )->getId,
|
||||
});
|
||||
}
|
||||
$newAsset->update({ title => $newAsset->getTitle . ' (copy)'});
|
||||
|
||||
$tree->success($asset->getId);
|
||||
$process->update(sub { $tree->json });
|
||||
|
||||
my $tag = WebGUI::VersionTag->getWorking($session);
|
||||
if ($tag->canAutoCommit) {
|
||||
$tag->commit;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use strict;
|
|||
use Class::C3;
|
||||
use base qw/WebGUI::AssetHelper::Copy/;
|
||||
use Scalar::Util qw{ blessed };
|
||||
use WebGUI::VersionTag;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
|
|
@ -122,17 +123,16 @@ sub copyBranch {
|
|||
$process->update(sub { $tree->json });
|
||||
my $newAsset = $asset->duplicateBranch( $args->{childrenOnly} ? 1 : 0, 'clipboard' );
|
||||
|
||||
# If we aren't committing, add to a tag
|
||||
if ( !$args->{commit} ) {
|
||||
$newAsset->update({
|
||||
status => "pending",
|
||||
tagId => WebGUI::VersionTag->getWorking( $session )->getId,
|
||||
});
|
||||
}
|
||||
$newAsset->update({ title => $newAsset->getTitle . ' (copy)'});
|
||||
|
||||
$tree->success($asset->getId);
|
||||
$process->update(sub { $tree->json });
|
||||
|
||||
my $tag = WebGUI::VersionTag->getWorking($session);
|
||||
if ($tag->canAutoCommit) {
|
||||
$tag->commit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ sub process {
|
|||
my $import = WebGUI::Asset->getImportNode( $session );
|
||||
my $tag = WebGUI::VersionTag->getWorking( $session );
|
||||
my $child = $import->addChild({
|
||||
tagId => $tag->getId,
|
||||
status => 'pending',
|
||||
className => 'WebGUI::Asset::Shortcut',
|
||||
shortcutToAssetId => $asset->getId,
|
||||
title => $asset->getTitle,
|
||||
|
|
|
|||
|
|
@ -73,13 +73,6 @@ sub duplicate {
|
|||
$process->update(sub { $tree->json });
|
||||
my $newAsset = $asset->duplicate;
|
||||
|
||||
# If we aren't committing, add to a tag
|
||||
if ( !$args->{commit} ) {
|
||||
$newAsset->update({
|
||||
status => "pending",
|
||||
tagId => WebGUI::VersionTag->getWorking( $session )->getId,
|
||||
});
|
||||
}
|
||||
$newAsset->update({ title => $newAsset->getTitle . ' (Duplicate)'});
|
||||
|
||||
$tree->success($asset->getId);
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ sub www_editBranchSave {
|
|||
my $revision;
|
||||
if (scalar %$newData > 0) {
|
||||
$revision = $descendant->addRevision(
|
||||
{ %$newData, tagId => $tag->getId, status => "pending" },
|
||||
{ %$newData, },
|
||||
undef,
|
||||
{skipAutoCommitWorkflows => 1, skipNotification => 1},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -157,8 +157,7 @@ sub www_cropSave {
|
|||
return $session->privilege->locked() unless $asset->canEditIfLocked;
|
||||
|
||||
my $tag = WebGUI::VersionTag->getWorking( $session );
|
||||
$asset = $asset->addRevision({ tagId => $tag->getId, status => "pending" });
|
||||
$asset->setVersionLock;
|
||||
$asset = $asset->addRevision();
|
||||
delete $asset->{_storageLocation};
|
||||
$asset->getStorageLocation->crop(
|
||||
$asset->filename,
|
||||
|
|
@ -171,7 +170,7 @@ sub www_cropSave {
|
|||
WebGUI::VersionTag->autoCommitWorkingIfEnabled($session, { allowComments => 0 });
|
||||
|
||||
# We're in admin mode, close the dialog
|
||||
my $helper = { message => 'Image croped', };
|
||||
my $helper = { message => 'Image cropped', };
|
||||
my $text = '<script type="text/javascript">';
|
||||
|
||||
if ( ref $helper eq 'HASH' ) {
|
||||
|
|
|
|||
|
|
@ -146,8 +146,7 @@ sub www_resizeSave {
|
|||
return $session->privilege->insufficient() unless $asset->canEdit;
|
||||
return $session->privilege->locked() unless $asset->canEditIfLocked;
|
||||
my $tag = WebGUI::VersionTag->getWorking($session);
|
||||
$asset = $asset->addRevision( { tagId => $tag->getId, status => "pending" } );
|
||||
$asset->setVersionLock;
|
||||
$asset = $asset->addRevision();
|
||||
delete $asset->{_storageLocation};
|
||||
$asset->getStorageLocation->resize(
|
||||
$asset->filename,
|
||||
|
|
|
|||
|
|
@ -91,8 +91,7 @@ sub www_rotateSave {
|
|||
return $session->privilege->locked() unless $asset->canEditIfLocked;
|
||||
|
||||
my $tag = WebGUI::VersionTag->getWorking( $session );
|
||||
$asset = $asset->addRevision({ tagId => $tag->getId, status => "pending" });
|
||||
$asset->setVersionLock;
|
||||
$asset = $asset->addRevision();
|
||||
delete $asset->{_storageLocation};
|
||||
$asset->getStorageLocation->rotate($asset->filename,$session->form->process("Rotate"));
|
||||
$asset->setSize($asset->getStorageLocation->getFileSize($asset->filename));
|
||||
|
|
|
|||
|
|
@ -53,12 +53,7 @@ sub process {
|
|||
return { error => sprintf $i18n->get('already locked'), $asset->getTitle};
|
||||
}
|
||||
|
||||
my $tag = WebGUI::VersionTag->getWorking( $session );
|
||||
$asset = $asset->addRevision({
|
||||
tagId => $tag->getId,
|
||||
status => "pending",
|
||||
});
|
||||
$asset->setVersionLock;
|
||||
$asset->addRevision;
|
||||
return {
|
||||
message => sprintf($i18n->get('locked asset'), $asset->getTitle),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,31 @@ sub addRevision {
|
|||
my $now = shift || time();
|
||||
my $options = shift;
|
||||
|
||||
my $autoCommitId = $self->getAutoCommitWorkflowId() unless ($options->{skipAutoCommitWorkflows});
|
||||
|
||||
my ($workingTag, $oldWorking);
|
||||
if ( $autoCommitId ) {
|
||||
$workingTag
|
||||
= WebGUI::VersionTag->create( $self->session, {
|
||||
groupToUse => '12', # Turn Admin On (for lack of something better)
|
||||
workflowId => $autoCommitId,
|
||||
} );
|
||||
}
|
||||
else {
|
||||
my $parentAsset;
|
||||
if ( not defined( $parentAsset = $self->getParent ) ) {
|
||||
$parentAsset = WebGUI::Asset->newPending( $self->session, $self->get('parentId') );
|
||||
}
|
||||
if ( $parentAsset->hasBeenCommitted ) {
|
||||
$workingTag = WebGUI::VersionTag->getWorking( $self->session );
|
||||
}
|
||||
else {
|
||||
$oldWorking = WebGUI::VersionTag->getWorking($self->session, 'noCreate');
|
||||
$workingTag = WebGUI::VersionTag->new( $self->session, $parentAsset->get('tagId') );
|
||||
$workingTag->setWorking();
|
||||
}
|
||||
}
|
||||
|
||||
#Create a dummy revision to be updated with real data later
|
||||
$session->db->beginTransaction;
|
||||
|
||||
|
|
@ -109,7 +134,7 @@ sub addRevision {
|
|||
$session->db->commit;
|
||||
|
||||
# current values, and the user set properties
|
||||
my %mergedProperties = (%{$self->get}, %{$properties}, );
|
||||
my %mergedProperties = (%{$self->get}, %{$properties}, tagId => $workingTag->getId, status => 'pending', );
|
||||
|
||||
# Set some defaults
|
||||
$mergedProperties{ revisedBy } = $properties->{ revisedBy } || $session->user->userId;
|
||||
|
|
@ -121,7 +146,10 @@ sub addRevision {
|
|||
my $newVersion = WebGUI::Asset->newById($session, $self->getId, $now);
|
||||
$newVersion->setSkipNotification if ($options->{skipNotification});
|
||||
$newVersion->updateHistory("created revision");
|
||||
$newVersion->setVersionLock;
|
||||
$newVersion->update(\%mergedProperties);
|
||||
$newVersion->setAutoCommitTag($workingTag) if (defined $autoCommitId);
|
||||
$oldWorking->setWorking if $oldWorking;
|
||||
|
||||
return $newVersion;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ sub sendRequestToMaster {
|
|||
};
|
||||
return 1 unless $@;
|
||||
undef $pipe;
|
||||
$self->session->log->error('Problems talking to master daemon process. Please restart the web server.');
|
||||
$self->session->log->error("Problems talking to master daemon process: $@. Please restart the web server.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Returns the amount of credit that is owed to this user.
|
|||
|
||||
sub getSum {
|
||||
my $self = shift;
|
||||
my $credit = $self->session->db->quickScalar("select sum(amount) from shopCredit where userId=?",[$self->userId]);
|
||||
my $credit = $self->session->db->quickScalar("select sum(amount) from shopCredit where userId=?",[$self->userId]) || 0;
|
||||
return sprintf("%.2f", $credit);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,44 +76,44 @@ sub execute {
|
|||
# keep track of how much time it's taking
|
||||
my $start = time;
|
||||
my $limit = 2_500;
|
||||
my $timeLimit = 60;
|
||||
my $timeLimit = $self->getTTL;
|
||||
|
||||
my $list = $root->getLineage( ['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::EMSSubmissionForm'],
|
||||
returnObjects => 1,
|
||||
} );
|
||||
|
||||
includeOnlyClasses => ['WebGUI::Asset::EMSSubmissionForm'],
|
||||
returnObjects => 1,
|
||||
} );
|
||||
|
||||
for my $emsForm ( @$list ) {
|
||||
my $whereClause = q{ submissionStatus='approved' };
|
||||
my $res = $emsForm->getLineage(['children'],{ returnObjects => 1,
|
||||
joinClass => 'WebGUI::Asset::EMSSubmission',
|
||||
includeOnlyClasses => ['WebGUI::Asset::EMSSubmission'],
|
||||
whereClause => $whereClause,
|
||||
returnObjects => 1,
|
||||
} );
|
||||
for my $submission ( @$res ) {
|
||||
my $properties = { className => 'WebGUI::Asset::Sku::EMSTicket' };
|
||||
my $res = $emsForm->getLineage(['children'], {
|
||||
returnObjects => 1,
|
||||
joinClass => 'WebGUI::Asset::EMSSubmission',
|
||||
includeOnlyClasses => ['WebGUI::Asset::EMSSubmission'],
|
||||
whereClause => ,q{ submissionStatus='approved' },
|
||||
returnObjects => 1,
|
||||
} );
|
||||
for my $submission ( @$res ) {
|
||||
my $properties = { className => 'WebGUI::Asset::Sku::EMSTicket' };
|
||||
for my $name ( qw{title description seatsAvailable price vendorId
|
||||
synopsis location duration startDate sku relatedRibbons
|
||||
relatedBadgeGroups eventMetaData shipsSeparately} ) {
|
||||
$properties->{$name} = $submission->get($name);
|
||||
$properties->{$name} = $submission->get($name);
|
||||
}
|
||||
$properties->{eventNumber} = $self->session->db->quickScalar(
|
||||
"select max(eventNumber)+1
|
||||
from EMSTicket left join asset using (assetId)
|
||||
where parentId=?",[$emsForm->ems->getId]) || 0;
|
||||
"select max(eventNumber)+1 from EMSTicket left join asset using (assetId)
|
||||
where parentId=?",[$emsForm->ems->getId]) || 0;
|
||||
my $newAsset = $emsForm->ems->addChild( $properties );
|
||||
if( $newAsset ) {
|
||||
# TODO this should be addRevision
|
||||
$submission->update({ ticketId => $newAsset->getId, submissionStatus => 'created' });
|
||||
WebGUI::VersionTag->autoCommitWorkingIfEnabled($session, { override => 1, allowComments => 0 });
|
||||
} else {
|
||||
# TODO this should be addRevision
|
||||
$submission->update({ ticketId => $newAsset->getId, submissionStatus => 'created' });
|
||||
WebGUI::VersionTag->autoCommitWorkingIfEnabled($session, { override => 1, allowComments => 0 });
|
||||
}
|
||||
else {
|
||||
$submission->addComment($@) if $@;
|
||||
$submission->update({ submissionStatus => 'failed' });
|
||||
}
|
||||
$limit--;
|
||||
last if ! $limit or time > $start + $timeLimit;
|
||||
}
|
||||
$submission->update({ submissionStatus => 'failed' });
|
||||
}
|
||||
$limit--;
|
||||
last if ! $limit or time > $start + $timeLimit;
|
||||
}
|
||||
}
|
||||
return $self->WAITING(1) if ! $limit or time > $start + $timeLimit;
|
||||
return $self->COMPLETE;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue