mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-10 00:11:22 +08:00
adds custom query to fetch teams data
This commit is contained in:
parent
782daabce1
commit
db16da7bd6
12 changed files with 141 additions and 39 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,4 +108,4 @@ DataTable.propTypes = {
|
|||
data: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default DataTable;
|
||||
export default DataTable;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
5
spec/factories/user_teams.rb
Normal file
5
spec/factories/user_teams.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
FactoryGirl.define do
|
||||
factory :user_team do
|
||||
role 'admin'
|
||||
end
|
||||
end
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue