From b1dcaf9c77473a1dea3dbe7c081b7fa501d13dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20Rama=C5=A1euski?= <andrej@x2.cz> Date: Fri, 2 Dec 2022 00:16:28 +0100 Subject: [PATCH] Refactoring, podpora hostu mimo skupiny --- lib/SeMeet/Controller/Auth.pm | 2 +- lib/SeMeet/Controller/Meets.pm | 79 +++++++------ lib/SeMeet/Controller/Users.pm | 1 + lib/SeMeet/Helpers/Core.pm | 11 +- lib/SeMeet/I18N/cs.pm | 6 +- lib/SeMeet/Schema/Result/Meet.pm | 31 ++++- lib/SeMeet/Schema/Result/MeetUser.pm | 32 +++++ lib/SeMeet/Schema/Result/MeetUser_view.pm | 20 ++++ lib/SeMeet/Schema/Result/Moderator.pm | 23 ---- openapi.yaml | 38 +++--- sql/migrations.sql | 19 +++ templates/includes/meet.html.ep | 2 +- templates/includes/meet_groups.html.ep | 14 +-- templates/includes/meet_moderators.html.ep | 18 +-- templates/includes/meet_participants.html.ep | 29 +++++ templates/meet.html.ep | 116 ++++++++++--------- 16 files changed, 287 insertions(+), 154 deletions(-) create mode 100644 lib/SeMeet/Schema/Result/MeetUser.pm create mode 100644 lib/SeMeet/Schema/Result/MeetUser_view.pm delete mode 100644 lib/SeMeet/Schema/Result/Moderator.pm create mode 100644 templates/includes/meet_participants.html.ep diff --git a/lib/SeMeet/Controller/Auth.pm b/lib/SeMeet/Controller/Auth.pm index 96b8605..503bbca 100644 --- a/lib/SeMeet/Controller/Auth.pm +++ b/lib/SeMeet/Controller/Auth.pm @@ -6,7 +6,7 @@ sub callback ($c) { my $token = $c->oidc->get_access_token( $c->param("code") ); my $claims = $c->oauth_claims( $token->access_token ); - my $octopus_user = $c->iapi->get('octopus/user?username=' . $claims->{preferred_username}); + my $octopus_user = $c->iapi->get('octopus/users/' . $claims->{sub}); my %user = ( uuid => $claims->{sub}, diff --git a/lib/SeMeet/Controller/Meets.pm b/lib/SeMeet/Controller/Meets.pm index 27935af..8325967 100644 --- a/lib/SeMeet/Controller/Meets.pm +++ b/lib/SeMeet/Controller/Meets.pm @@ -47,12 +47,22 @@ sub get($c) { my $args = $c->req->json; my $meet = $c->_get($c->stash->{id}, 0) // return; - my $is_mod = $meet->moderators({ octid => $c->stash->{user}->id})->count; + + my $users = { 0 => [], 1 => [] }; + + USER: + foreach my $user ( $meet->users ) { + push @{ $users->{ $user->is_moderator} }, { + id => $user->id, + name => $user->user_name, + } + } $c->render(openapi => $c->spec_filter({ $meet->get_columns, - groups => $meet->cached_groups, - moderators => $meet->cached_moderators, + groups => $meet->cached_groups, #TODO: direct + moderators => $users->{1}, + participants => $users->{0}, }, 'Meet')); } @@ -64,13 +74,13 @@ sub list($c) { deleted => undef, -or => [ owner_id => $c->stash->{user}->id, - "groups.group_id" => { '-in' => $c->stash->{groups} }, - "moderators.octid" => $c->stash->{user}->octid, + "meet_groups.group_id" => { '-in' => $c->stash->{groups} }, + "meet_users.user_id" => $c->stash->{user}->id, ] }, { order_by => 'name', - join => ['groups', 'moderators'], + join => ['meet_groups', 'meet_users'], distinct => 1, } ); @@ -81,10 +91,9 @@ sub list($c) { while ( my $meet = $meets->next()) { push @meets, $c->spec_filter({ $meet->get_columns, - groups => $meet->cached_groups, - moderators => $meet->cached_moderators, -# is_owned => ( $meet->owner_id == $c->stash->{user}->id), -# is_moderated => 0, + groups => $meet->cached_groups, + moderators => $meet->cached_moderators, + participants => [], }, 'Meet') } @@ -113,48 +122,50 @@ sub add_groups($c) { $c->render( status => 204, text => '' ); } -sub add_moderators($c) { +sub delete_group($c) { $c->openapi->valid_input or return; - my $args = $c->req->json; - - my $meet = $c->_get($c->stash->{id}, 2) // return; - IDS: - foreach my $user ( @{ $args->{users} } ) { + my $meet = $c->_get($c->stash->{id}, 1) // return; - $meet->find_or_create_related('moderators', - { - octid => $user->{id}, - name => $user->{name}, - } - ); - } - $meet->update_moderators_cache(); + $meet->delete_related('meet_groups', + { group_id => $c->stash->{group_id} } + ); + $meet->update_groups_cache(); $c->render( status => 204, text => '' ); } -sub delete_group($c) { +sub add_users($c) { $c->openapi->valid_input or return; + my $args = $c->req->json; - my $meet = $c->_get($c->stash->{id}, 1) // return; + my $meet = $c->_get($c->stash->{id}, 2) // return; + my $is_moderator = $args->{kind} eq 'moderator' ? 't':'f'; - $meet->delete_related('meet_groups', - { group_id => $c->stash->{group_id} } - ); - $meet->update_groups_cache(); + UUID: + foreach my $uuid ( @{ $args->{users} } ) { + my $user = $c->user_by_uuid($uuid) // next UUID; + $meet->find_or_create_related('meet_users', + { + user_id => $user->id, + is_moderator => $is_moderator, + } + ); + } + $meet->update_moderators_cache() if $is_moderator; $c->render( status => 204, text => '' ); } -sub delete_moderator($c) { +sub delete_user($c) { $c->openapi->valid_input or return; my $meet = $c->_get($c->stash->{id}, 2) // return; - $meet->delete_related('moderators', - { octid => $c->stash->{user_id} } + $meet->delete_related('meet_users', + { id => $c->stash->{relation_id} } ); + $meet->update_moderators_cache(); $c->render( status => 204, text => '' ); @@ -205,6 +216,8 @@ sub meet($c) { #NENI API! return $c->error(404, 'NOT_FOUND') if ! $meet; my $roles = $meet->user_roles($user, $c->current_user->{groups}); + $c->trace($roles); + return $c->error(404, 'NOT_FOUND') if ! $roles->{any}; diff --git a/lib/SeMeet/Controller/Users.pm b/lib/SeMeet/Controller/Users.pm index e3ea8df..7a9f0ea 100644 --- a/lib/SeMeet/Controller/Users.pm +++ b/lib/SeMeet/Controller/Users.pm @@ -55,6 +55,7 @@ sub list($c) { push @users, $c->spec_filter({ id => $user->{id}, + uuid => $user->{uuid}, name => $user->{displayname}, username => $user->{username}, region => join ' - ', grep { defined } ($ks, $ms), diff --git a/lib/SeMeet/Helpers/Core.pm b/lib/SeMeet/Helpers/Core.pm index f135ce8..05d4277 100644 --- a/lib/SeMeet/Helpers/Core.pm +++ b/lib/SeMeet/Helpers/Core.pm @@ -104,22 +104,23 @@ sub register { return $data; }); - $self->helper( user_by_octid => sub ($c, $octid) { + $self->helper( user_by_uuid => sub ($c, $uuid) { my $user = $c->schema->resultset('User')->find({ - octid => $octid + uuid => $uuid }); if ( ! $user ) { - my $octopus_user = $c->iapi->get("octopus/users/$octid"); + my $octopus_user = $c->iapi->get("octopus/users/$uuid"); if ( $octopus_user ) { $user = $c->schema->resultset('User')->find_or_create( { - octid => $octid, + uuid => $uuid, + octid => $octopus_user->{id}, username => $octopus_user->{username}, displayname => $octopus_user->{displayname}, }, - { key => 'username' } + { key => 'uuid' } ); } } diff --git a/lib/SeMeet/I18N/cs.pm b/lib/SeMeet/I18N/cs.pm index 207ecc6..f6102fc 100644 --- a/lib/SeMeet/I18N/cs.pm +++ b/lib/SeMeet/I18N/cs.pm @@ -19,18 +19,22 @@ our %Lexicon = ( ERROR_MEET_NAME_REQURED => "Název novĂ© mĂstnosti je povinnĂ˝", ERROR_MEET_NAME_DUPLICITY => 'DuplicitnĂ název mistnosti', LABEL_GROUPS_ADD => 'PĹ™idánĂ skupin', - LABEL_USERS_ADD => 'PĹ™idánĂ moderatorĹŻ', ENTER => 'Vstoupit', COPY_LINK => 'ZkopĂrovat odkaz', 'About meet' => 'O mistnosti', 'Add groups' => 'PĹ™idat skupiny', 'Add moderators' => 'PĹ™idat moderatory', + 'Add people' => 'PĹ™idat osoby', 'Create meet' => 'VytvoĹ™it mĂstnost', 'Delete meet' => 'Smazat mĂstnost', 'Save changes' => 'UloĹľit zmÄ›ny', 'Configuration' => 'Konfigurace', 'Authorized groups' => 'OpravnÄ›nĂ© skupiny', + 'Authorized persons' => 'OpravnÄ›nĂ© osoby', + 'Adding groups' => 'PĹ™idávánĂ skupin', + 'Adding people' => 'PĹ™idávánĂ osob', + 'Adding moderators' => 'PĹ™idávánĂ moderatorĹŻ', 'Moderators' => 'ModeratoĹ™i', 'Invites' => 'Pozvánky', ); diff --git a/lib/SeMeet/Schema/Result/Meet.pm b/lib/SeMeet/Schema/Result/Meet.pm index 991a547..aaa221c 100644 --- a/lib/SeMeet/Schema/Result/Meet.pm +++ b/lib/SeMeet/Schema/Result/Meet.pm @@ -51,7 +51,7 @@ __PACKAGE__->has_many( ); __PACKAGE__->has_many( - moderators => 'SeMeet::Schema::Result::Moderator', + meet_users => 'SeMeet::Schema::Result::MeetUser', { 'foreign.meet_id' => 'self.id', }, ); @@ -60,6 +60,11 @@ __PACKAGE__->has_many( { 'foreign.meet_id' => 'self.id', }, ); +__PACKAGE__->has_many( + users => 'SeMeet::Schema::Result::MeetUser_view', + { 'foreign.meet_id' => 'self.id', }, +); + __PACKAGE__->inflate_column('properties', { inflate => sub { from_json(shift); }, deflate => sub { to_json(shift); }, @@ -68,8 +73,22 @@ __PACKAGE__->inflate_column('properties', { sub user_roles($self, $user, $groups) { my $roles = { - participant => $self->meet_groups({ group_id => { -in => $groups } })->count(), - moderator => $self->moderators({ octid => $user->octid })->count(), + + participant => ( + $self->meet_groups({ + group_id => { -in => $groups } + })->count() + || + $self->meet_users({ + user_id => $user->id, + })->count() + ), + + moderator => $self->meet_users({ + user_id => $user->id, + is_moderator => 't', + })->count(), + owner => ($self->owner_id == $user->id), }; @@ -93,10 +112,10 @@ sub update_groups_cache($self) { sub update_moderators_cache($self) { my @moderators = (); - foreach my $moderator ($self->moderators) { + foreach my $moderator ($self->users({ is_moderator => 't'})) { push @moderators, { - id => $moderator->octid, - name => $moderator->name, + id => $moderator->id, + name => $moderator->user_name, }; } my $properties = $self->properties // {}; diff --git a/lib/SeMeet/Schema/Result/MeetUser.pm b/lib/SeMeet/Schema/Result/MeetUser.pm new file mode 100644 index 0000000..10daf68 --- /dev/null +++ b/lib/SeMeet/Schema/Result/MeetUser.pm @@ -0,0 +1,32 @@ +package SeMeet::Schema::Result::MeetUser; + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + +our $VERSION = 1; + +__PACKAGE__->table('meets_users'); + +__PACKAGE__->add_columns( + id => { + data_type => 'integer', + is_auto_increment => 1, + is_nullable => 0, + sequence => 'uid_seq' + }, + qw( + meet_id + user_id + is_moderator + ), +); + +__PACKAGE__->set_primary_key('id'); + +__PACKAGE__->add_unique_constraint( + secondary => [qw(meet_id user_id is_moderator)] +); + +1; diff --git a/lib/SeMeet/Schema/Result/MeetUser_view.pm b/lib/SeMeet/Schema/Result/MeetUser_view.pm new file mode 100644 index 0000000..6d5c37b --- /dev/null +++ b/lib/SeMeet/Schema/Result/MeetUser_view.pm @@ -0,0 +1,20 @@ +package SeMeet::Schema::Result::MeetUser_view; + +use strict; +use warnings; + +use base 'SeMeet::Schema::Result::MeetUser'; + +our $VERSION = 1; + +__PACKAGE__->table('meets_users_view'); + +__PACKAGE__->add_columns( + qw( + user_name + ), +); + +1; + + diff --git a/lib/SeMeet/Schema/Result/Moderator.pm b/lib/SeMeet/Schema/Result/Moderator.pm deleted file mode 100644 index 4491de9..0000000 --- a/lib/SeMeet/Schema/Result/Moderator.pm +++ /dev/null @@ -1,23 +0,0 @@ -package SeMeet::Schema::Result::Moderator; - -use strict; -use warnings; - -use base 'DBIx::Class::Core'; - -our $VERSION = 1; - -__PACKAGE__->table('moderators'); - -__PACKAGE__->add_columns( - qw( - meet_id - octid - name - ), -); - -__PACKAGE__->set_primary_key('meet_id', 'octid'); - -1; - diff --git a/openapi.yaml b/openapi.yaml index 5672914..21fdd2c 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -48,6 +48,10 @@ components: type: array items: $ref: '#/components/schemas/UserInList' + participants: + type: array + items: + $ref: '#/components/schemas/UserInList' GroupInList: type: object properties: @@ -63,6 +67,9 @@ components: id: type: integer readOnly: true + uuid: + type: string + readOnly: true name: type: string readOnly: true @@ -272,7 +279,7 @@ paths: items: $ref: '#/components/schemas/UserInList' - /meets/{id}/group: + /meets/{id}/groups: post: x-mojo-to: meets#add_groups security: @@ -307,7 +314,7 @@ paths: 201: description: Groups authorized - /meets/{id}/group/{group_id}: + /meets/{id}/groups/{group_id}: delete: x-mojo-to: meets#delete_group security: @@ -335,15 +342,15 @@ paths: 204: description: Groups unauthorized - /meets/{id}/moderator: + /meets/{id}/users: post: - x-mojo-to: meets#add_moderators + x-mojo-to: meets#add_users security: - Bearer: [] tags: - meets - summary: "Pridat moderatory" - operationId: addModeratorsToMeet + summary: "Pridat osoby/moderatory" + operationId: addUsersToMeet parameters: - name: id in: path @@ -362,23 +369,22 @@ paths: users: type: array items: - type: object -# $ref: '#/components/schemas/UserInList' + type: string required: - users responses: 201: - description: Moderators added + description: Users added - /meets/{id}/moderator/{user_id}: + /meets/{id}/users/{relation_id}: delete: - x-mojo-to: meets#delete_moderator + x-mojo-to: meets#delete_user security: - Bearer: [] tags: - meets - summary: "Smazat moderatora" - operationId: deleteModeratorFromMeet + summary: "Smazat osobu" + operationId: deleteUserFromMeet parameters: - name: id in: path @@ -387,13 +393,13 @@ paths: description: "Identifikator mistnosti" schema: type: integer - - name: user_id + - name: relation_id in: path required: true example: 100345 - description: "Identifikator moderatora" + description: "Identifikator relace" schema: type: integer responses: 204: - description: Moderator deleted + description: User deleted diff --git a/sql/migrations.sql b/sql/migrations.sql index 04f4887..8e1e977 100644 --- a/sql/migrations.sql +++ b/sql/migrations.sql @@ -62,3 +62,22 @@ create table "moderators" ( foreign key ("meet_id") references "meets" ("id") on update cascade on delete cascade ); +-- 5 up +create table "meets_users" ( + "id" integer not null default nextval('uid_seq'), + "meet_id" integer not null, + "user_id" integer not null, + "is_moderator" bool not null default 'f', + primary key("id"), + unique("meet_id", "user_id", "is_moderator"), + foreign key ("meet_id") references "meets" ("id") on update cascade on delete cascade, + foreign key ("user_id") references "users" ("id") on update cascade on delete cascade +); + +create view "meets_users_view" as +select "meets_users".*, + "users"."displayname" as "user_name" +from "meets_users" +join "users" on ("users"."id" = "meets_users"."user_id") +; + diff --git a/templates/includes/meet.html.ep b/templates/includes/meet.html.ep index 72b4028..feadf7c 100644 --- a/templates/includes/meet.html.ep +++ b/templates/includes/meet.html.ep @@ -36,6 +36,6 @@ }, }; - const jitsi = new JitsiMeetExternalAPI(MEET_DOMAIN, MEET_OPTIONS); +// const jitsi = new JitsiMeetExternalAPI(MEET_DOMAIN, MEET_OPTIONS); </script> diff --git a/templates/includes/meet_groups.html.ep b/templates/includes/meet_groups.html.ep index 29545c3..b53c518 100644 --- a/templates/includes/meet_groups.html.ep +++ b/templates/includes/meet_groups.html.ep @@ -10,16 +10,16 @@ </div> % if ( $roles->{owner} || $roles->{moderator} ) { -<div class="" v-effect="searchGroups()"> - <label class="form-field__label" for="name"><%=l 'LABEL_GROUPS_ADD' %></label> - <input type="text" class="w-full text-input" value="" v-model="search_groups" id="search_group" placeholder="<%=l 'INPUT_MEET_ADD_GROUPS_PLACEHOLDER' %>"/> - <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="groups.length > 0"> - <div v-for="group in groups" class="checkbox form-field__control mb-1" > - <input name="groups" type="checkbox" v-bind:title="group.id" v-bind:value="group.id" v-model="selected_groups" > +<div v-effect="searchGroups()"> + <label class="form-field__label" for="name"><%=l 'Adding groups' %></label> + <input type="text" class="w-full text-input" value="" v-model="filter['group']" id="search_group" placeholder="<%=l 'INPUT_MEET_ADD_GROUPS_PLACEHOLDER' %>"/> + <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="search['group'].length > 0"> + <div v-for="group in search['group']" class="checkbox form-field__control mb-1" > + <input name="groups" type="checkbox" v-bind:title="group.id" v-bind:value="group.id" v-model="selected['group']" > <label>{{group.name}}</label> </div> </div> - <div class="form-field" v-if="selected_groups.length > 0"> + <div class="form-field" v-if="selected['group'].length > 0"> <button class="btn btn--green-400 btn--hoveractive text-lg" @click="addGroups()"> <div class="btn__body"><%=l 'Add groups' %></div> </button> diff --git a/templates/includes/meet_moderators.html.ep b/templates/includes/meet_moderators.html.ep index 2b637bb..5ae1dc6 100644 --- a/templates/includes/meet_moderators.html.ep +++ b/templates/includes/meet_moderators.html.ep @@ -3,24 +3,24 @@ {{ moderator.name }} % if ( $roles->{owner} ) { <span class="icon"> - <i class="ico--cross ml-3 cursor-pointer" @click="removeModerator(moderator.id)"></i> + <i class="ico--cross ml-3 cursor-pointer" @click="removeUser(moderator.id)"></i> </span> % } </span> </div> % if ( $roles->{owner} ) { -<div v-effect="searchUsers()"> - <label class="form-field__label" for="name"><%=l 'LABEL_USERS_ADD' %></label> - <input type="text" class="w-full text-input" value="" v-model="search_users" id="search_user" placeholder="<%=l 'INPUT_MEET_ADD_USERS_PLACEHOLDER' %>"/> - <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="users.length > 0"> - <div v-for="user in users" class="checkbox form-field__control mb-1" > - <input name="users" type="checkbox" v-bind:title="user.id" v-bind:value="user.id" v-model="selected_users" > +<div v-effect="searchUsers('moderator')"> + <label class="form-field__label" for="name"><%=l 'Adding moderators' %></label> + <input type="text" class="w-full text-input" value="" v-model="filter['moderator']" id="search_moderator" placeholder="<%=l 'INPUT_MEET_ADD_USERS_PLACEHOLDER' %>"/> + <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="search['moderator'].length > 0"> + <div v-for="user in search['moderator']" class="checkbox form-field__control mb-1" > + <input name="moderators" type="checkbox" :value="user.uuid" v-model="selected['moderator']" > <label style="max-width: 100%">{{user.name}} ({{ user.username }})<span v-if="user.region.length > 0" class="text-grey-300 text-xs"> | {{ user.region }}</span></label> </div> </div> - <div class="form-field" v-if="selected_users.length > 0"> - <button class="btn btn--red-600 btn--hoveractive text-lg" @click="addModerators()"> + <div class="form-field" v-if="selected['moderator'].length > 0"> + <button class="btn btn--red-600 btn--hoveractive text-lg" @click="addUsers('moderator')"> <div class="btn__body"><%=l 'Add moderators' %></div> </button> </div> diff --git a/templates/includes/meet_participants.html.ep b/templates/includes/meet_participants.html.ep new file mode 100644 index 0000000..f2427aa --- /dev/null +++ b/templates/includes/meet_participants.html.ep @@ -0,0 +1,29 @@ +<div class="mb-4"> +<span v-for="user in meet.participants" class="chip chip--blue-300 mr-1 mb-1 rounded"> +{{ user.name }} +% if ( $roles->{owner} || $roles->{moderator} ) { + <span class="icon"> + <i class="ico--cross ml-3 cursor-pointer" @click="removeUser(user.id)"></i> + </span> +% } +</span> +</div> + +% if ( $roles->{owner} || $roles->{moderator} ) { +<div v-effect="searchUsers('participant')"> + <label class="form-field__label" for="name"><%=l 'Adding people' %></label> + <input type="text" class="w-full text-input" value="" v-model="filter['participant']" id="search_participant" placeholder="<%=l 'INPUT_MEET_ADD_USERS_PLACEHOLDER' %>"/> + <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="search['participant'].length > 0"> + <div v-for="user in search['participant']" class="checkbox form-field__control mb-1" > + <input name="participants" type="checkbox" :value="user.uuid" v-model="selected['participant']" > + <label style="max-width: 100%">{{user.name}} ({{ user.username }})<span v-if="user.region.length > 0" class="text-grey-300 text-xs"> | {{ user.region }}</span></label> + </div> + </div> + <div class="form-field" v-if="selected['participant'].length > 0"> + <button class="btn btn--blue-300 btn--hoveractive text-lg" @click="addUsers('participant')"> + <div class="btn__body"><%=l 'Add people' %></div> + </button> + </div> +</div> +% } + diff --git a/templates/meet.html.ep b/templates/meet.html.ep index d9904a9..485b5d8 100644 --- a/templates/meet.html.ep +++ b/templates/meet.html.ep @@ -3,8 +3,9 @@ %= include 'includes/meet' -<div class="grid grid-cols-3 border border-b-0 divide-x text-center"> +<div class="grid grid-cols-4 border border-b-0 divide-x text-center"> <div @click="active_tab='groups'" class="p-4 bg-grey-125" :class="tabClass('groups')"><%=l 'Authorized groups' %></div> +<div @click="active_tab='participants'" class="p-4 bg-grey-125" :class="tabClass('participants')"><%=l 'Authorized persons' %></div> <div @click="active_tab='moderators'" class="p-4 bg-grey-125" :class="tabClass('moderators')"><%=l 'Moderators' %></div> %#<div @click="active_tab='invites'" class="p-4 bg-grey-125" :class="tabClass('invites')"><%=l 'Invites' %></div> <div @click="active_tab='form'" class="p-4 bg-grey-125" :class="tabClass('form')"><%=l $roles->{owner} ? 'Configuration':'About meet' %></div> @@ -13,6 +14,9 @@ <div class="border p-4" v-effect="getMeet()" v-cloak> <div v-if="active_tab == 'groups'"> %= include 'includes/meet_groups' + </div> + <div v-if="active_tab == 'participants'"> +%= include 'includes/meet_participants' </div> <div v-if="active_tab == 'moderators'"> %= include 'includes/meet_moderators' @@ -33,10 +37,9 @@ const GROUPS_URL = '/api/groups'; const USERS_URL = '/api/users'; -//const USERS_URL = '<%= config->{iapi} %>octopus/users'; const MEET_URL = '/api/meets/<%= stash->{id} %>'; - const ADD_GROUPS_URL = '/api/meets/<%= stash->{id} %>/group'; - const ADD_USERS_URL = '/api/meets/<%= stash->{id} %>/moderator'; + const ADD_GROUPS_URL = '/api/meets/<%= stash->{id} %>/groups'; + const ADD_USERS_URL = '/api/meets/<%= stash->{id} %>/users'; const API_HEADERS = { "Content-Type": "application/json", "Accept": "application/json", @@ -45,20 +48,28 @@ createApp({ - title: '', meet: {}, - users: {}, active_tab: 'groups', delete_confirm_visible: false, - search_groups: '', - search_users: '', + filter: { + group: '', + participant: '', + moderator: '', + }, + + search: { + group: '', + participant: '', + moderator: '', + }, - groups: [], - users: [], - selected_groups: [], - selected_users: [], + selected: { + group: [], + participant: [], + moderator: [], + }, tabClass(id) { if (id == this.active_tab) { @@ -80,6 +91,31 @@ }) }, + searchUsers(kind) { + if ( this.filter[kind].length < 2 ) { + this.search[kind] = []; + return true; + } + + fetch(USERS_URL + '?search=' + this.filter[kind] ) + .then((res) => res.json()) + .then(res => { + this.search[kind] = res; + }) + }, + + searchGroups() { + if ( this.filter['group'].length < 2 ) { + this.search['group'] = []; + return true; + } + + fetch(GROUPS_URL + '?search=' + this.filter['group'] ) + .then((res) => res.json()) + .then(res => { + this.search['group'] = res; + }) + }, % if ( $roles->{owner} ) { updateMeet() { @@ -94,19 +130,6 @@ .then() }, - searchUsers() { - if ( this.search_users.length < 2 ) { - this.users = []; - return true; - } - - fetch(USERS_URL + '?search=' + this.search_users ) - .then((res) => res.json()) - .then(res => { - this.users = res; - }) - }, - deleteMeet() { fetch(MEET_URL, { method: "DELETE", @@ -120,29 +143,32 @@ }); }, - addModerators() { - if ( this.selected_users.length == 0) { +% } +% if ( $roles->{owner} || $roles->{moderator} ) { + + addUsers(kind) { + if ( this.selected[kind].length == 0) { return true; } - const selected = this.users.filter(item => this.selected_users.includes(item.id)) + const selected = this.search[kind].filter(item => this.selected[kind].includes(item.id)) fetch(ADD_USERS_URL, { method: "POST", headers: API_HEADERS, - body: JSON.stringify({ users: selected }), + body: JSON.stringify({ users: this.selected[kind], kind: kind }), }) .then((response) => { if (response.ok) { - this.selected_users =[] - this.search_users = '' + this.selected[kind] =[] + this.filter[kind] = '' this.getMeet() } }) }, - removeModerator(id) { - fetch(MEET_URL + '/moderator/' + id, { + removeUser(id, kind) { + fetch(MEET_URL + '/users/' + id, { method: "DELETE", headers: API_HEADERS, }) @@ -153,43 +179,29 @@ }) }, -% } - -% if ( $roles->{owner} || $roles->{moderator} ) { - searchGroups() { - if ( this.search_groups.length < 2 ) { - this.groups = []; - return true; - } - fetch(GROUPS_URL + '?search=' + this.search_groups ) - .then((res) => res.json()) - .then(res => { - this.groups = res; - }) - }, addGroups() { - if ( this.selected_groups.length == 0) { + if ( this.selected['group'].length == 0) { return true; } fetch(ADD_GROUPS_URL, { method: "POST", headers: API_HEADERS, - body: JSON.stringify({ groups: this.selected_groups }), + body: JSON.stringify({ groups: this.selected['group'] }), }) .then((response) => { if (response.ok) { - this.selected_groups =[] - this.search_groups = '' + this.selected['group'] =[] + this.filter['group'] = '' this.getMeet() } }) }, removeGroup(id) { - fetch(MEET_URL + '/group/' + id, { + fetch(MEET_URL + '/groups/' + id, { method: "DELETE", headers: API_HEADERS, }) -- GitLab