cicd
Some checks failed
Build And Deploy Main / build-and-deploy (push) Has been cancelled

This commit is contained in:
2026-03-09 12:31:10 -04:00
parent 63ee52adc4
commit 914985517c
7 changed files with 150 additions and 5 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -0,0 +1,101 @@
name: Build And Deploy Main
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on:
- self-hosted
- mayo-cicd
env:
PROJECT_DIR: ~/temp/tspt
REMOTE_HOST: 34.232.175.208
REMOTE_USER: rocky
SSH_KEY: ~/ssh-certs/charlie_ws.pem
REMOTE_APP_ROOT: /www/wwwroot/worldshine1
REMOTE_VIEWS_DIR: /www/wwwroot/worldshine1/app/views
EXCLUDE_PATTERN: (^|/)\.DS_Store$|(^|/)_MACOSX(/|$)
BEFORE_SHA: ${{ github.event.before }}
AFTER_SHA: ${{ github.sha }}
steps:
- name: Validate project checkout
run: |
set -e
if [ ! -d "$PROJECT_DIR/.git" ]; then
echo "Expected git repository at $PROJECT_DIR but not found."
exit 1
fi
- name: Pull latest main
run: |
set -e
cd "$PROJECT_DIR"
git fetch origin main
git checkout main
git pull origin main
- name: Build client
run: |
set -e
cd "$PROJECT_DIR/client"
npm install
npm run build
- name: Replace local app views from client dist
run: |
set -e
cd "$PROJECT_DIR"
mkdir -p app/views
rm -rf app/views/*
rsync -a --delete --exclude ".DS_Store" --exclude "_MACOSX" client/dist/ app/views/
- name: Deploy views to remote server
run: |
set -e
cd "$PROJECT_DIR"
SSH_CMD="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
RSYNC_RSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
$SSH_CMD "$REMOTE_USER@$REMOTE_HOST" "mkdir -p \"$REMOTE_VIEWS_DIR\""
rsync -az --delete --exclude ".DS_Store" --exclude "_MACOSX" -e "$RSYNC_RSH" app/views/ "$REMOTE_USER@$REMOTE_HOST:$REMOTE_VIEWS_DIR/"
- name: Deploy changed backend files only
run: |
set -e
cd "$PROJECT_DIR"
SSH_CMD="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
RSYNC_RSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
CHANGE_PATHS=(app/controllers app/middlewares app/models app/routes app/scheduler app/services)
if [ -n "$BEFORE_SHA" ] && [ "$BEFORE_SHA" != "0000000000000000000000000000000000000000" ]; then
CHANGED_FILES=$(git diff --name-only "$BEFORE_SHA" "$AFTER_SHA" -- "${CHANGE_PATHS[@]}" | rg -v "$EXCLUDE_PATTERN" || true)
DELETED_FILES=$(git diff --name-only --diff-filter=D "$BEFORE_SHA" "$AFTER_SHA" -- "${CHANGE_PATHS[@]}" | rg -v "$EXCLUDE_PATTERN" || true)
else
CHANGED_FILES=$(git show --name-only --pretty="" "$AFTER_SHA" -- "${CHANGE_PATHS[@]}" | rg -v "$EXCLUDE_PATTERN" || true)
DELETED_FILES=""
fi
if [ -z "$CHANGED_FILES" ]; then
echo "No backend file changes detected in target folders."
else
while IFS= read -r file; do
[ -z "$file" ] && continue
[ -f "$file" ] || continue
remote_file="$REMOTE_APP_ROOT/$file"
remote_dir=$(dirname "$remote_file")
$SSH_CMD "$REMOTE_USER@$REMOTE_HOST" "mkdir -p \"$remote_dir\""
rsync -az --exclude ".DS_Store" --exclude "_MACOSX" -e "$RSYNC_RSH" "$file" "$REMOTE_USER@$REMOTE_HOST:$remote_file"
echo "Deployed: $file"
done <<< "$CHANGED_FILES"
fi
if [ -n "$DELETED_FILES" ]; then
while IFS= read -r file; do
[ -z "$file" ] && continue
remote_file="$REMOTE_APP_ROOT/$file"
$SSH_CMD "$REMOTE_USER@$REMOTE_HOST" "rm -f \"$remote_file\""
echo "Deleted on remote: $file"
done <<< "$DELETED_FILES"
fi

BIN
app/.DS_Store vendored

Binary file not shown.

View File

@@ -15,7 +15,8 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo,
driverName, vehicle, relatedOutbound,
vehicles, isInbound, deleteFile,
keyword, statusFilter, customerNameFilter,
customerTableId, routeTypeFilter, customerTypeFilter
customerTableId, routeTypeFilter, customerTypeFilter,
onRouteUpdated = null
}) => {
const [show, setShow] = useState(false);
const [showGroupEditor, setShowGroupEditor] = useState(false);
@@ -223,6 +224,9 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo,
if (dateStr !== '' && dateStr !== moment().format('MM/DD/YYYY')) {
finalParams = Object.assign({}, finalParams, {dateText: dateStr})
}
if (onRouteUpdated) {
finalParams = Object.assign({}, finalParams, {callback: onRouteUpdated})
}
dispatch(updateRoute(finalParams));
// if (removeSignature && deleteFile) {
// deleteFile();
@@ -276,6 +280,9 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo,
if (dateStr !== '' && dateStr !== moment().format('MM/DD/YYYY')) {
finalParams = Object.assign({}, finalParams, {dateText: dateStr})
}
if (onRouteUpdated) {
finalParams = Object.assign({}, finalParams, {callback: onRouteUpdated})
}
dispatch(updateRoute(finalParams));
// if (removeSignature && deleteFile) {
// deleteFile();
@@ -628,6 +635,9 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo,
if (dateStr !== '' && dateStr !== moment().format('MM/DD/YYYY')) {
finalParams = Object.assign({}, finalParams, {dateText: dateStr})
}
if (onRouteUpdated) {
finalParams = Object.assign({}, finalParams, {callback: onRouteUpdated})
}
// Log final payload before dispatch, especially for Wang,Huanran
const wangCustomer = finalParams.data.route_customer_list?.find(c =>

View File

@@ -5,7 +5,8 @@ const PersonnelSection = ({transRoutes, sectionName, showCompletedInfo,
showGroupInfo, allowForceEdit, showFilter,
driverName, vehicle, relatedOutbound,
vehicles, isInbound, deleteFile, keyword,
statusFilter, customerTypeFilter, customerNameFilter, customerTableId, routeTypeFilter
statusFilter, customerTypeFilter, customerNameFilter, customerTableId, routeTypeFilter,
onRouteUpdated = null
}) => {
return (
<>
@@ -21,6 +22,7 @@ const PersonnelSection = ({transRoutes, sectionName, showCompletedInfo,
customerNameFilter={customerNameFilter}
customerTable={customerTableId}
routeTypeFilter={routeTypeFilter}
onRouteUpdated={onRouteUpdated}
/>
</div>
</div>

View File

@@ -16,11 +16,13 @@ const ItemTypes = {
const Card = ({ content, index, moveCard }) => {
const ref = useRef(null);
const [{ handlerId }, drop] = useDrop({
const [{ handlerId, isOver, draggedIndex }, drop] = useDrop({
accept: ItemTypes.CARD,
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
isOver: monitor.isOver({ shallow: true }),
draggedIndex: monitor.getItem()?.index,
}
},
drop(item, monitor) {
@@ -72,9 +74,21 @@ const Card = ({ content, index, moveCard }) => {
}),
})
const opacity = isDragging ? 0 : 1
const showDropTopIndicator = isOver && draggedIndex !== undefined && draggedIndex > index;
const showDropBottomIndicator = isOver && draggedIndex !== undefined && draggedIndex < index;
const dropZoneStyle = {
opacity,
paddingTop: '10px',
paddingBottom: '10px',
borderRadius: '8px',
backgroundColor: isOver ? '#eef6ff' : 'transparent',
borderTop: showDropTopIndicator ? '4px solid #0d6efd' : '4px solid transparent',
borderBottom: showDropBottomIndicator ? '4px solid #0d6efd' : '4px solid transparent',
transition: 'background-color 0.12s ease, border-color 0.12s ease'
};
drag(drop(ref))
return (
<div ref={ref} style={{ opacity }} data-handler-id={handlerId}>
<div ref={ref} style={dropZoneStyle} data-handler-id={handlerId}>
{content}
</div>
)

View File

@@ -26,6 +26,7 @@ const RouteView = () => {
const [signatureRequest, setSignatureRequest] = useState(undefined);
const [routeStatusValue, setRouteStatusValue] = useState('');
const [isSavingRouteStatus, setIsSavingRouteStatus] = useState(false);
const [latestRouteForStatus, setLatestRouteForStatus] = useState(undefined);
const paramsQuery = new URLSearchParams(window.location.search);
const scheduleDate = paramsQuery.get('dateSchedule');
@@ -40,6 +41,7 @@ const RouteView = () => {
{ value: ROUTE_STATUS.SIGN_OFF, label: 'Signed Off' },
{ value: ROUTE_STATUS.UNEXPECTED_ABSENT, label: 'Unexpected Absent' },
];
const routeForStatusView = latestRouteForStatus || currentRoute;
const closeModal = () => {
setShowVehicleDetails(false);
}
@@ -109,11 +111,27 @@ const RouteView = () => {
}
};
const refreshRouteStatusData = async () => {
if (!currentRoute?.id) return;
try {
const response = await TransRoutesService.getRoute(currentRoute.id);
if (response?.data) {
setLatestRouteForStatus(response.data);
}
} catch (error) {
console.error('Error refreshing route status data:', error);
}
};
useEffect(() => {
const currentStatus = Array.isArray(currentRoute?.status) ? currentRoute.status[0] : '';
setRouteStatusValue(currentStatus || '');
}, [currentRoute?.id, currentRoute?.status]);
useEffect(() => {
setLatestRouteForStatus(undefined);
}, [currentRoute?.id]);
useEffect(() => {
if (!currentRoute?.driver || currentDriver?.id) {
setFallbackDriver(undefined);
@@ -268,7 +286,7 @@ const RouteView = () => {
</div>
</div>
<div className="col-md-12 mb-4">
{currentRoute && <PersonnelSection transRoutes={[currentRoute]} showCompletedInfo={true} showGroupInfo={true} isInbound={currentRoute?.type === 'inbound' } allowForceEdit={AuthService.canViewRoutes()} sectionName="Personnel Status (click on each user to edit)" relatedOutbound={getRelatedOutboundRoutesForThisView()} vehicle={currentVehicle} driverName={resolvedDriverName} deleteFile={deleteFile}/>}
{routeForStatusView && <PersonnelSection transRoutes={[routeForStatusView]} showCompletedInfo={true} showGroupInfo={true} isInbound={routeForStatusView?.type === 'inbound' } allowForceEdit={AuthService.canViewRoutes()} sectionName="Personnel Status (click on each user to edit)" relatedOutbound={getRelatedOutboundRoutesForThisView()} vehicle={currentVehicle} driverName={resolvedDriverName} deleteFile={deleteFile} onRouteUpdated={refreshRouteStatusData}/>}
</div>
</div>
</Tab>