@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
//Update row highlighting on production board.
|
//Update row highlighting on production board.
|
||||||
.ant-table-tbody > tr.ant-table-row:hover > td {
|
.ant-table-tbody > tr.ant-table-row:hover > td {
|
||||||
background: #eaeaea !important;
|
background: #e7f3ff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.job-line-manual {
|
.job-line-manual {
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ import { selectSelectedConversation } from "../../redux/messaging/messaging.sele
|
|||||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
import { List as VirtualizedList, AutoSizer } from "react-virtualized";
|
import {
|
||||||
|
List as VirtualizedList,
|
||||||
|
AutoSizer,
|
||||||
|
CellMeasurerCache,
|
||||||
|
CellMeasurer,
|
||||||
|
} from "react-virtualized";
|
||||||
|
|
||||||
import "./chat-conversation-list.styles.scss";
|
import "./chat-conversation-list.styles.scss";
|
||||||
|
|
||||||
@@ -33,48 +38,64 @@ function ChatConversationListComponent({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const rowRenderer = ({ index, key, style }) => {
|
const cache = new CellMeasurerCache({
|
||||||
|
fixedWidth: true,
|
||||||
|
defaultHeight: 60,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rowRenderer = ({ index, key, style, parent }) => {
|
||||||
const item = conversationList[index];
|
const item = conversationList[index];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<CellMeasurer
|
||||||
key={key}
|
key={key}
|
||||||
onClick={() => setSelectedConversation(item.id)}
|
cache={cache}
|
||||||
className={`chat-list-item ${
|
parent={parent}
|
||||||
item.id === selectedConversation
|
columnIndex={0}
|
||||||
? "chat-list-selected-conversation"
|
rowIndex={index}
|
||||||
: null
|
|
||||||
}`}
|
|
||||||
style={style}
|
|
||||||
>
|
>
|
||||||
<div sryle={{ display: "inline-block" }}>
|
<List.Item
|
||||||
{item.label && <div className="chat-name">{item.label}</div>}
|
onClick={() => setSelectedConversation(item.id)}
|
||||||
{item.job_conversations.length > 0 ? (
|
className={`chat-list-item ${
|
||||||
<div className="chat-name">
|
item.id === selectedConversation
|
||||||
{item.job_conversations.map((j, idx) => (
|
? "chat-list-selected-conversation"
|
||||||
<div key={idx}>
|
: null
|
||||||
<OwnerNameDisplay ownerObject={j.job} />
|
}`}
|
||||||
</div>
|
style={style}
|
||||||
))}
|
>
|
||||||
</div>
|
<div
|
||||||
) : (
|
style={{
|
||||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
display: "inline-block",
|
||||||
)}
|
}}
|
||||||
</div>
|
>
|
||||||
<div sryle={{ display: "inline-block" }}>
|
{item.label && <div className="chat-name">{item.label}</div>}
|
||||||
<div>
|
{item.job_conversations.length > 0 ? (
|
||||||
{item.job_conversations.length > 0
|
<div className="chat-name">
|
||||||
? item.job_conversations.map((j, idx) => (
|
{item.job_conversations.map((j, idx) => (
|
||||||
<Tag key={idx} className="ro-number-tag">
|
<div key={idx}>
|
||||||
{j.job.ro_number}
|
<OwnerNameDisplay ownerObject={j.job} />
|
||||||
</Tag>
|
</div>
|
||||||
))
|
))}
|
||||||
: null}
|
</div>
|
||||||
|
) : (
|
||||||
|
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
<div style={{ display: "inline-block" }}>
|
||||||
</div>
|
<div>
|
||||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
{item.job_conversations.length > 0
|
||||||
</List.Item>
|
? item.job_conversations.map((j, idx) => (
|
||||||
|
<Tag key={idx} className="ro-number-tag">
|
||||||
|
{j.job.ro_number}
|
||||||
|
</Tag>
|
||||||
|
))
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
||||||
|
</div>
|
||||||
|
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||||
|
</List.Item>
|
||||||
|
</CellMeasurer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,7 +107,7 @@ function ChatConversationListComponent({
|
|||||||
height={height}
|
height={height}
|
||||||
width={width}
|
width={width}
|
||||||
rowCount={conversationList.length}
|
rowCount={conversationList.length}
|
||||||
rowHeight={60}
|
rowHeight={cache.rowHeight}
|
||||||
rowRenderer={rowRenderer}
|
rowRenderer={rowRenderer}
|
||||||
onScroll={({ scrollTop, scrollHeight, clientHeight }) => {
|
onScroll={({ scrollTop, scrollHeight, clientHeight }) => {
|
||||||
if (scrollTop + clientHeight === scrollHeight) {
|
if (scrollTop + clientHeight === scrollHeight) {
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
import { Space } from "antd";
|
import { Space, Button, Col } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||||
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
|
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
|
||||||
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
||||||
import ChatLabelComponent from "../chat-label/chat-label.component";
|
import ChatLabelComponent from "../chat-label/chat-label.component";
|
||||||
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
||||||
|
import { LeftOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
export default function ChatConversationTitle({ conversation }) {
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
setSelectedConversation: (conversationId) =>
|
||||||
|
dispatch(setSelectedConversation(conversationId)),
|
||||||
|
});
|
||||||
|
|
||||||
|
function ChatConversationTitle({ conversation, setSelectedConversation }) {
|
||||||
return (
|
return (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
|
<Col sm={0}>
|
||||||
|
<Button
|
||||||
|
onClick={() => setSelectedConversation()}
|
||||||
|
size="small"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
<LeftOutlined />
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
<PhoneNumberFormatter>
|
<PhoneNumberFormatter>
|
||||||
{conversation && conversation.phone_num}
|
{conversation && conversation.phone_num}
|
||||||
</PhoneNumberFormatter>
|
</PhoneNumberFormatter>
|
||||||
@@ -23,3 +40,5 @@ export default function ChatConversationTitle({ conversation }) {
|
|||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(ChatConversationTitle);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export function ChatPopupComponent({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Row gutter={[8, 8]} className="chat-popup-content">
|
<Row gutter={[8, 8]} className="chat-popup-content">
|
||||||
<Col span={8}>
|
<Col span={8} sm={8} xs={selectedConversation && 0}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -311,7 +311,9 @@ function Header({
|
|||||||
icon={<SettingOutlined />}
|
icon={<SettingOutlined />}
|
||||||
>
|
>
|
||||||
<Menu.Item key="shop" icon={<Icon component={GiSettingsKnobs} />}>
|
<Menu.Item key="shop" icon={<Icon component={GiSettingsKnobs} />}>
|
||||||
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
|
<Link to="/manage/shop?tab=info">
|
||||||
|
{t("menus.header.shop_config")}
|
||||||
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="dashboard" icon={<DashboardFilled />}>
|
<Menu.Item key="dashboard" icon={<DashboardFilled />}>
|
||||||
<Link to="/manage/dashboard">{t("menus.header.dashboard")}</Link>
|
<Link to="/manage/dashboard">{t("menus.header.dashboard")}</Link>
|
||||||
|
|||||||
@@ -108,7 +108,12 @@ export function JobsConvertButton({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Select>
|
<Select
|
||||||
|
showSearch
|
||||||
|
filterOption={(input, option) => {
|
||||||
|
return option.value.toLowerCase().includes(input.toLowerCase());
|
||||||
|
}}
|
||||||
|
>
|
||||||
{bodyshop.md_ins_cos.map((s, i) => (
|
{bodyshop.md_ins_cos.map((s, i) => (
|
||||||
<Select.Option key={i} value={s.name}>
|
<Select.Option key={i} value={s.name}>
|
||||||
{s.name}
|
{s.name}
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) {
|
|||||||
<Tabs
|
<Tabs
|
||||||
defaultActiveKey={search.subtab}
|
defaultActiveKey={search.subtab}
|
||||||
onChange={(key) =>
|
onChange={(key) =>
|
||||||
history.push({ search: `?tab=${search.tab}&subtab=${key}` })
|
history.push({
|
||||||
|
search: `?tab=${search.tab}&subtab=${key}`,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Tabs.TabPane key="general" tab={t("bodyshop.labels.shopinfo")}>
|
<Tabs.TabPane key="general" tab={t("bodyshop.labels.shopinfo")}>
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
|
|||||||
]);
|
]);
|
||||||
}, [t, setSelectedHeader, setBreadcrumbs, bodyshop.shopname]);
|
}, [t, setSelectedHeader, setBreadcrumbs, bodyshop.shopname]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!search.tab) history.push({ search: "?tab=info" });
|
||||||
|
}, [history, search]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RbacWrapper action="shop:config">
|
<RbacWrapper action="shop:config">
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
@@ -2690,6 +2690,13 @@
|
|||||||
table:
|
table:
|
||||||
name: inventory
|
name: inventory
|
||||||
schema: public
|
schema: public
|
||||||
|
- name: parts_dispatch_lines
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on:
|
||||||
|
column: joblineid
|
||||||
|
table:
|
||||||
|
name: parts_dispatch_lines
|
||||||
|
schema: public
|
||||||
- name: parts_order_lines
|
- name: parts_order_lines
|
||||||
using:
|
using:
|
||||||
foreign_key_constraint_on:
|
foreign_key_constraint_on:
|
||||||
@@ -3131,6 +3138,13 @@
|
|||||||
table:
|
table:
|
||||||
name: notes
|
name: notes
|
||||||
schema: public
|
schema: public
|
||||||
|
- name: parts_dispatches
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on:
|
||||||
|
column: jobid
|
||||||
|
table:
|
||||||
|
name: parts_dispatch
|
||||||
|
schema: public
|
||||||
- name: parts_orders
|
- name: parts_orders
|
||||||
using:
|
using:
|
||||||
foreign_key_constraint_on:
|
foreign_key_constraint_on:
|
||||||
@@ -4556,6 +4570,165 @@
|
|||||||
template_engine: Kriti
|
template_engine: Kriti
|
||||||
url: '{{$base_url}}/opensearch'
|
url: '{{$base_url}}/opensearch'
|
||||||
version: 2
|
version: 2
|
||||||
|
- table:
|
||||||
|
name: parts_dispatch
|
||||||
|
schema: public
|
||||||
|
object_relationships:
|
||||||
|
- name: job
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: jobid
|
||||||
|
array_relationships:
|
||||||
|
- name: parts_dispatch_lines
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on:
|
||||||
|
column: partsdispatchid
|
||||||
|
table:
|
||||||
|
name: parts_dispatch_lines
|
||||||
|
schema: public
|
||||||
|
insert_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- id
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- jobid
|
||||||
|
- number
|
||||||
|
- employeeid
|
||||||
|
- dispatched_at
|
||||||
|
- dispatched_by
|
||||||
|
select_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- number
|
||||||
|
- dispatched_by
|
||||||
|
- created_at
|
||||||
|
- dispatched_at
|
||||||
|
- updated_at
|
||||||
|
- employeeid
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
filter:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
update_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- number
|
||||||
|
- dispatched_by
|
||||||
|
- created_at
|
||||||
|
- dispatched_at
|
||||||
|
- updated_at
|
||||||
|
- employeeid
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
filter:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
check: null
|
||||||
|
- table:
|
||||||
|
name: parts_dispatch_lines
|
||||||
|
schema: public
|
||||||
|
object_relationships:
|
||||||
|
- name: jobline
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: joblineid
|
||||||
|
- name: parts_dispatch
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: partsdispatchid
|
||||||
|
insert_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- id
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- partsdispatchid
|
||||||
|
- joblineid
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
select_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- id
|
||||||
|
- joblineid
|
||||||
|
- partsdispatchid
|
||||||
|
filter:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
update_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- id
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- partsdispatchid
|
||||||
|
- joblineid
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
filter:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
check: null
|
||||||
- table:
|
- table:
|
||||||
name: parts_order_lines
|
name: parts_order_lines
|
||||||
schema: public
|
schema: public
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines" drop constraint "parts_dispatch_lines_partsdispatchid_fkey";
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines"
|
||||||
|
add constraint "parts_dispatch_lines_partsdispatchid_fkey"
|
||||||
|
foreign key ("partsdispatchid")
|
||||||
|
references "public"."parts_dispatch"
|
||||||
|
("id") on update cascade on delete cascade;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines" alter column "accepted_at" set not null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines" alter column "accepted_at" drop not null;
|
||||||
Reference in New Issue
Block a user