adds custom query to fetch teams data

This commit is contained in:
zmagod 2017-08-25 16:07:37 +02:00
parent 782daabce1
commit db16da7bd6
12 changed files with 141 additions and 39 deletions

View file

@ -37,11 +37,11 @@ module ClientApi
end
def teams
{ teams: current_user.teams }
{ teams: current_user.teams_data }
end
def change_current_team
team_id = params.fetch(:team_id) { raise MissingTeamError }
team_id = params.fetch(:team_id) { raise MissingTeamError }
unless current_user.teams.pluck(:id).include? team_id
raise MissingTeamError
end

View file

@ -14,6 +14,9 @@ export default {
all_teams: "All teams",
in_team: "You are member of {num} team",
in_teams: "You are member of {num} team",
leave_team_modal: {
title: "Leave team {teamName}"
},
account: "Account",
team: "Team",
avatar: "Avatar",

View file

@ -1,8 +1,8 @@
import { SHOW_LEAVE_TEAM_MODAL } from "../../app/action_types";
export function leaveTeamModalShow(show, id) {
export function leaveTeamModalShow(show, id, teamName) {
return({
payload: { show, id },
payload: { show, id, teamName },
type: SHOW_LEAVE_TEAM_MODAL
});
}

View file

@ -108,4 +108,4 @@ DataTable.propTypes = {
data: PropTypes.arrayOf(PropTypes.object).isRequired
};
export default DataTable;
export default DataTable;

View file

@ -1,15 +1,21 @@
import React, { Component } from "react";
import PropTypes, { bool, number, string } from "prop-types";
import { Modal, Button } from "react-bootstrap";
import _ from "lodash";
import { FormattedMessage } from "react-intl";
import { connect } from "react-redux";
class LeaveTeamModal extends Component {
render() {
return (
<Modal show={this.props.showModal}>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage id="activities.modal_title" />
<FormattedMessage
id="settings_page.leave_team_modal.title"
values={{ teamName: this.props.teamName }}
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>BANANAN</Modal.Body>
@ -23,9 +29,24 @@ class LeaveTeamModal extends Component {
}
}
LeaveTeamModal.propTypes = {
showModal: bool.isRequired,
teamId: number.isRequired,
teamName: string.isRequired,
teams: PropTypes.arrayOf(
PropTypes.shape({
id: number.isRequired,
name: string.isRequired,
current_team: bool.isRequired,
role: string.isRequired,
members: number.isRequired,
}).isRequired
)
};
const mapStateToProps = ({ showLeaveTeamModal }) => ({
showModal: showLeaveTeamModal.show,
teamId: showLeaveTeamModal.id
teamId: showLeaveTeamModal.id,
teamName: showLeaveTeamModal.teamName
});
export default connect(mapStateToProps)(LeaveTeamModal);

View file

@ -1,8 +1,11 @@
import { SHOW_LEAVE_TEAM_MODAL } from '../../app/action_types'
import { SHOW_LEAVE_TEAM_MODAL } from "../../app/action_types";
export function showLeaveTeamModal(state = {show: false, id: 0}, action) {
if(action.type ===SHOW_LEAVE_TEAM_MODAL) {
return {...state, ...action.payload}
export function showLeaveTeamModal(
state = { show: false, id: 0, teamName: "" },
action
) {
if (action.type === SHOW_LEAVE_TEAM_MODAL) {
return { ...state, ...action.payload };
}
return state
return state;
}

View file

@ -1,5 +1,5 @@
import React from "react";
import PropTypes from "prop-types";
import PropTypes, { number, string, bool } from "prop-types";
import styled from "styled-components";
import { connect } from "react-redux";
import { FormattedMessage } from "react-intl";
@ -38,9 +38,11 @@ const SettingsTeams = ({ teams }) =>
SettingsTeams.propTypes = {
teams: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
current_team: PropTypes.bool.isRequired
id: number.isRequired,
name: string.isRequired,
current_team: bool.isRequired,
role: string.isRequired,
members: number.isRequired,
}).isRequired
)
};

View file

@ -1,5 +1,4 @@
import React, { Component } from "react";
import { TableHeaderColumn } from "react-bootstrap-table";
import { connect } from "react-redux";
import { Button } from "react-bootstrap";
import { leaveTeamModalShow } from "../../../../../shared/actions/LeaveTeamActions";
@ -8,12 +7,14 @@ import DataTable from "../../../../../shared/data_table";
class TeamsDataTable extends Component {
constructor(props) {
super(props);
this.leaveTeamModal = this.leaveTeamModal.bind(this);
this.leaveTeamButton = this.leaveTeamButton.bind(this);
}
leaveTeamModal(e, id) {
e.peventDefault();
this.props.leaveTeamModalShow(true, id);
const team = _.find(this.props.teams, el => el.id === id);
this.props.leaveTeamModalShow(true, id, team.name);
}
leaveTeamButton(id) {
@ -23,23 +24,33 @@ class TeamsDataTable extends Component {
}
render() {
return (
<DataTable data={this.props.teams}>
<TableHeaderColumn isKey dataField="name">
Name
</TableHeaderColumn>
<TableHeaderColumn dataField="role">Role</TableHeaderColumn>
<TableHeaderColumn dataField="members">Memebers</TableHeaderColumn>
<TableHeaderColumn dataField="id" dataFormat={this.leaveTeamButton} />
</DataTable>
);
const columns = [
{ id: "name", name: "Name", isKey: false, textId: "name", position: 0 },
{ id: "role", name: "Role", isKey: false, textId: "role", position: 1 },
{
id: "members",
name: "Members",
isKey: false,
textId: "members",
position: 2
},
{
id: "id",
name: "",
isKey: true,
textId: "id",
dataFormat: this.leaveTeamButton,
position: 3
}
];
return <DataTable data={this.props.teams} columns={columns} />;
}
}
//
// const mapDispatchToProps = dispatch => ({
// leaveTeamModalShow(show, id) {
// dispatch(leaveTeamModalShow(show, id));
// }
// });
const mapDispatchToProps = dispatch => ({
leaveTeamModalShow(show, id) {
dispatch(leaveTeamModalShow(show, id));
}
});
export default connect(null, mapDispatchToProps)(TeamsDataTable);
export default connect(null, { leaveTeamModalShow })(TeamsDataTable);

View file

@ -204,6 +204,21 @@ class User < ApplicationRecord
Team.find_by_id(self.current_team_id)
end
# Retrieves the data needed in all teams page
def teams_data
ActiveRecord::Base.connection.execute(
ActiveRecord::Base.send(
:sanitize_sql_array,
['SELECT teams.id AS id, teams.name AS name, user_teams.role ' \
'AS role, (SELECT COUNT(*) FROM user_teams WHERE ' \
'user_teams.team_id = teams.id) AS members, ' \
'CASE WHEN teams.id=? THEN true ELSE false END AS current_team ' \
'FROM teams INNER JOIN user_teams ON teams.id=user_teams.team_id ' \
'WHERE user_teams.user_id=?', self.current_team_id, self.id]
)
)
end
# Search all active users for username & email. Can
# also specify which team to ignore.
def self.search(

View file

@ -1,7 +1,9 @@
json.teams do
json.collection teams do |team|
json.id team.id
json.name team.name
json.current_team team == current_user.current_team
json.id team.fetch('id')
json.name team.fetch('name')
json.members team.fetch('members')
json.role UserTeam.roles.keys[team.fetch('role')]
json.current_team team.fetch('current_team')
end
end

View file

@ -0,0 +1,5 @@
FactoryGirl.define do
factory :user_team do
role 'admin'
end
end

View file

@ -149,4 +149,44 @@ describe User, type: :model do
expect(user.name).to eq 'Axe'
end
end
describe 'teams_data should return a list of teams' do
# needs persistence because is testing a sql query
let(:team) { create :team }
let(:user_one) do
create :user, email: 'user1@asdf.com', current_team_id: team.id
end
let(:user_two) { create :user, email: 'user2@asdf.com' }
it 'in a specific format' do
create :user_team, team: team, user: user_one
expected_result = {
id: team.id,
name: team.name,
members: 1,
role: 2,
current_team: true
}
user_one.teams_data.first.each do |k, v|
expect(v).to eq(expected_result.fetch(k.to_sym))
end
end
it 'should return correct number of team members' do
create :user_team, team: team, user: user_one
create :user_team, team: team, user: user_two
expected_result = {
id: team.id,
name: team.name,
members: 2,
role: 2,
current_team: true
}
user_one.teams_data.first.each do |k, v|
expect(v).to eq(expected_result.fetch(k.to_sym))
end
end
end
end