Commit 375bc669 authored by Deni Rinaldi's avatar Deni Rinaldi

Merge branch 'syadziy' into 'master'

update redirect login

See merge request !215
parents 9db1674e 07bc1c51
......@@ -7,6 +7,7 @@ import format from "date-fns/format";
import localeID from "date-fns/locale/id"
import api from "../../api";
import Images from '../../assets/Images';
import Constant from '../../library/Constant';
export default class CreateApprovalMatrix extends Component {
constructor(props) {
......@@ -53,72 +54,119 @@ export default class CreateApprovalMatrix extends Component {
getUserData() {
api.create().getApprovedByAM().then((response) => {
if(response.status == null){
// alert(response.problem)
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
else if (response.data.status == 'success') {
let data = response.data.data
let userData = data.map((item) => {
return {
user_id: item.user_id,
fullname: item.fullname
if(response.data) {
if (response.ok) {
if (response.data.status == 'success') {
let data = response.data.data
let userData = data.map((item) => {
return {
user_id: item.user_id,
fullname: item.fullname
}
})
// console.log(userData)
let defaultProps = {
options: userData,
getOptionLabel: (option) => option.fullname,
};
this.setState({ approvedBy: defaultProps, userData: response.data.data})
} else {
// alert('Approver Name: ' +response.data.message)
if (response.data.message.includes("Token")) {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
})
} else {
this.setState({ alert: true, messageAlert: 'Approver Name: ' + response.data.message, tipeAlert: 'error' })
}
}
})
// console.log(userData)
let defaultProps = {
options: userData,
getOptionLabel: (option) => option.fullname,
};
this.setState({ approvedBy: defaultProps, userData: response.data.data})
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
} else {
// alert('Approver Name: ' +response.data.message)
this.setState({ alert: true, messageAlert: 'Approver Name: ' +response.problem, tipeAlert: 'error' })
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
})
}
getTypeData() {
api.create().getTypeAM().then((response) => {
if (response.data.status == 'success') {
let data = response.data.data
let typeData = data.map((item) => {
return {
approval_type_id: item.approval_type_id,
approval_type_name: item.approval_type_name
if (response.data) {
if (response.ok) {
if (response.data.status == 'success') {
let data = response.data.data
let typeData = data.map((item) => {
return {
approval_type_id: item.approval_type_id,
approval_type_name: item.approval_type_name
}
})
let typeProps = {
options: typeData,
getOptionLabel: (option) => option.approval_type_name,
};
this.setState({ types: typeProps, typeData: response.data.data })
} else {
// alert('Approval Type: ' +response.data.message)
if (response.data.message.includes("Token")) {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
})
} else {
this.setState({ alert: true, messageAlert: 'Approval Type: ' + response.data.message, tipeAlert: 'warning' })
}
}
})
let typeProps = {
options: typeData,
getOptionLabel: (option) => option.approval_type_name,
};
this.setState({ types: typeProps, typeData: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
} else {
// alert('Approval Type: ' +response.data.message)
this.setState({ alert: true, messageAlert: 'Approval Type: ' +response.problem, tipeAlert: 'error' })
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
})
}
getOperatorData() {
api.create().getOperatorAM().then((response) => {
if (response.data.status == 'success') {
let data = response.data.data
let operatorData = data.map((item) => {
return {
operator_type_id: item.operator_type_id,
operator_type_name: item.operator_type_name
if (response.data) {
if (response.ok) {
if (response.data.status == 'success') {
let data = response.data.data
let operatorData = data.map((item) => {
return {
operator_type_id: item.operator_type_id,
operator_type_name: item.operator_type_name
}
})
// console.log(userData)
let operatorProps = {
options: operatorData,
getOptionLabel: (option) => option.operator_type_name,
};
this.setState({ operators: operatorProps, operatorData: response.data.data })
} else {
// alert('Operator: ' +response.data.message)
if (response.data.message.includes("Token")) {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
})
} else {
this.setState({ alert: true, messageAlert: 'Operator: ' + response.data.message, tipeAlert: 'warning' })
}
}
})
// console.log(userData)
let operatorProps = {
options: operatorData,
getOptionLabel: (option) => option.operator_type_name,
};
this.setState({ operators: operatorProps, operatorData: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
} else {
// alert('Operator: ' +response.data.message)
this.setState({ alert: true, messageAlert: 'Operator: ' +response.problem, tipeAlert: 'error' })
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
})
}
......
......@@ -7,6 +7,7 @@ import ReactDragListView from 'react-drag-listview';
import Autocomplete from '@material-ui/lab/Autocomplete';
import api from "../../api";
import { none } from 'ramda';
import Constant from '../../library/Constant';
const type = [
......@@ -46,22 +47,33 @@ export default class VisualisasiAM extends Component {
getTypeData() {
api.create().getTypeAM().then((response) => {
if (response.data) {
if (response.data.status == 'success') {
let data = response.data.data
// console.log(data)
let typeData = data.map((item) => {
return {
approval_type_id: item.approval_type_id,
approval_type_name: item.approval_type_name
}
})
let typeProps = {
options: typeData,
getOptionLabel: (option) => option.approval_type_name,
};
this.setState({ types: typeProps, typeData: response.data.data })
if (response.ok) {
if (response.data.status == 'success') {
let data = response.data.data
// console.log(data)
let typeData = data.map((item) => {
return {
approval_type_id: item.approval_type_id,
approval_type_name: item.approval_type_name
}
})
let typeProps = {
options: typeData,
getOptionLabel: (option) => option.approval_type_name,
};
this.setState({ types: typeProps, typeData: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
}
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
......@@ -76,28 +88,39 @@ export default class VisualisasiAM extends Component {
}
api.create().searchAM(body).then(response => {
if (response.data) {
if (response.data.status == 'success') {
let data = response.data.data
// console.log(data)
let listVisual = []
data.map((item, index) => {
let indexId = listVisual.findIndex((val) => val.orderId == item.orders)
if(indexId == -1){
listVisual.push({
orderId: item.orders,
data: [item]
})
// console.log(listVisual);
} else {
listVisual[indexId].data.push(item)
// console.log('listVisual');
// console.log(listVisual);
}
})
this.setState({ listApproval: listVisual})
// console.log(listVisual);
if (response.ok) {
if (response.data.status == 'success') {
let data = response.data.data
// console.log(data)
let listVisual = []
data.map((item, index) => {
let indexId = listVisual.findIndex((val) => val.orderId == item.orders)
if(indexId == -1){
listVisual.push({
orderId: item.orders,
data: [item]
})
// console.log(listVisual);
} else {
listVisual[indexId].data.push(item)
// console.log('listVisual');
// console.log(listVisual);
}
})
this.setState({ listApproval: listVisual})
// console.log(listVisual);
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
}
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
......
This diff is collapsed.
This diff is collapsed.
......@@ -9,6 +9,7 @@ import api from '../../../api';
import { titleCase } from '../../../library/Utils';
import Autocomplete from '@material-ui/lab/Autocomplete';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const useStyles = makeStyles((theme) => ({
root: {
......@@ -94,7 +95,14 @@ export default class VisualReportItems extends Component {
this.setState({ listReport: defaultProps, report: reportData[0] })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -125,7 +133,14 @@ export default class VisualReportItems extends Component {
this.getItemHierarki()
})
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -212,7 +227,14 @@ export default class VisualReportItems extends Component {
}, 1000);
})
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -6,6 +6,7 @@ import format from "date-fns/format";
import Images from '../../../assets/Images';
import api from '../../../api';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const Alert = withStyles({
})((props) => <MuiAlert elevation={6} variant="filled" {...props} />);
......@@ -59,21 +60,32 @@ export default class CreateUnitBisnis extends Component {
api.create().getDetailUnitBisnis(this.props.data[1]).then(response => {
console.log(response)
if (response.data) {
if (response.data.status === "success") {
let data = response.data.data
this.setState({
id: data.business_unit_id,
name: data.business_unit_name,
startDate: data.start_date,
endDate: data.end_date,
status: data.status,
created: data.created,
updated: data.updated === null ? "" : data.updated
})
}
else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
}
if (response.ok) {
if (response.data.status === "success") {
let data = response.data.data
this.setState({
id: data.business_unit_id,
name: data.business_unit_name,
startDate: data.start_date,
endDate: data.end_date,
status: data.status,
created: data.created,
updated: data.updated === null ? "" : data.updated
})
}
else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
}
} else {
this.setState({ alert: true, messageAlert: response.problem, tipeAlert: 'error' })
}
......
This diff is collapsed.
......@@ -11,6 +11,7 @@ import { DatePicker } from '@material-ui/pickers';
import * as R from 'ramda'
import Images from '../../../assets/Images';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const CustomCheckbox = withStyles({
root: {
......@@ -200,7 +201,14 @@ export default class AddUser extends Component {
this.props.refresh()
}, 750);
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -235,7 +243,14 @@ export default class AddUser extends Component {
};
this.setState({ listRole: defaultProps })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -254,7 +269,14 @@ export default class AddUser extends Component {
this.setState({ listCompany: response.data.data })
console.log(response.data.data)
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -10,6 +10,7 @@ import AddIcon from '@material-ui/icons/Add';
import * as R from 'ramda'
import Images from '../../../assets/Images';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const CustomCheckbox = withStyles({
root: {
......@@ -145,7 +146,14 @@ export default class EditUser extends Component {
this.getRole(response.data.data.role_id))
console.log(response.data.data)
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -220,7 +228,14 @@ export default class EditUser extends Component {
console.log(index)
this.setState({ listRole: defaultProps, role: index === -1 ? null : roleData[index], msgErrorRN: index === -1 ? 'Role has been inactive' : '', errorRoleName: index === -1 ? true : false })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -238,7 +253,14 @@ export default class EditUser extends Component {
if (response.data.status === 'success') {
this.setState({ listCompany: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -13,6 +13,7 @@ import { InputBase, Snackbar } from "@material-ui/core";
import ReactTooltip from "react-tooltip";
import MuiAlert from '@material-ui/lab/Alert';
import { withStyles } from '@material-ui/core/styles';
import Constant from "../../library/Constant";
var ct = require("../../library/CustomTable");
const getMuiTheme = () => createMuiTheme(ct.customTable());
......@@ -68,7 +69,14 @@ class UserRole extends Component {
// })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -113,7 +121,14 @@ class UserRole extends Component {
})
this.setState({ listRole: listData })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -9,6 +9,7 @@ import localeID from "date-fns/locale/id"
import * as R from 'ramda'
import Images from '../../../assets/Images';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const CustomCheckbox = withStyles({
root: {
......@@ -143,7 +144,14 @@ export default class AddRole extends Component {
this.props.refresh()
}, 750);
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -188,7 +196,14 @@ export default class AddRole extends Component {
this.setState({ application: app, setting: set, isLoad: true }, () => console.log(this.state.application))
// this.setState({ menuData: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -8,6 +8,7 @@ import format from "date-fns/format";
import * as R from 'ramda'
import Images from '../../../assets/Images';
import MuiAlert from '@material-ui/lab/Alert';
import Constant from '../../../library/Constant';
const CustomCheckbox = withStyles({
root: {
......@@ -103,7 +104,14 @@ export default class EditRole extends Component {
this.setState({ tempData: response.data.data, privileges: response.data.data.privileges })
console.log(response.data.data.start_date)
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -163,7 +171,14 @@ export default class EditRole extends Component {
this.props.refresh()
}, 750);
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -208,7 +223,14 @@ export default class EditRole extends Component {
this.setState({ application: app, setting: set, isLoad: true }, () => console.log(this.state.application))
// this.setState({ menuData: response.data.data })
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
......@@ -120,7 +120,14 @@ export default class Profile extends Component {
window.location.reload();
}, 1000);
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -152,7 +159,14 @@ export default class Profile extends Component {
this.setState({ company: response.data.data.company, photo: response.data.data.photo, name: response.data.data.fullname })
console.log(response)
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -172,7 +186,14 @@ export default class Profile extends Component {
this.setState({ listCompany: response.data.data })
console.log(response.data.data)
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......@@ -311,7 +332,14 @@ export default class Profile extends Component {
})
})
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' })
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'warning' }, () => {
if (response.data.message.includes("Token")) {
setTimeout(() => {
localStorage.removeItem(Constant.TOKEN)
window.location.reload();
}, 1000);
}
})
}
} else {
this.setState({ alert: true, messageAlert: response.data.message, tipeAlert: 'error' })
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment