Prechádzať zdrojové kódy

1차 개발 완료 (날씨API 변경 포함)

ubitems_source 4 rokov pred
rodič
commit
2bef33a3d3
53 zmenil súbory, kde vykonal 2491 pridanie a 932 odobranie
  1. 1 1
      .vscode/settings.json
  2. 55 4
      README.md
  3. 1 0
      app.json
  4. 1 1
      package.json
  5. 0 2
      scripts/version_push.bat
  6. 1 3
      src/App.js
  7. 69 6
      src/Components/Hooks/index.js
  8. 7 3
      src/Components/Layouts/BottomTabBarLayout.js
  9. 24 22
      src/Components/Layouts/PopupLayout.js
  10. 1 1
      src/Components/Splash/index.js
  11. 2 2
      src/Components/UIControls/AnimatedContainer.js
  12. 17 6
      src/Components/UIControls/ImageViewer.js
  13. 52 1
      src/Components/UIControls/Input.js
  14. 1 1
      src/Components/UIControls/Message.js
  15. 7 1
      src/Components/UIControls/PopupSelect.js
  16. 16 16
      src/Components/UIControls/UploadFile.js
  17. 394 0
      src/Components/UIControls/dragdrop/index.tsx
  18. 13 3
      src/Screens/Drawer/index.js
  19. 224 0
      src/Screens/Independent/Popup/DragDropSample/index.js
  20. 4 2
      src/Screens/Independent/Popup/MaterialPurchaseOrder/index.js
  21. 19 13
      src/Screens/Independent/Popup/Scan/index.js
  22. 1 7
      src/Screens/Login/index.js
  23. 3 1
      src/Screens/Navigator.js
  24. 2 2
      src/Screens/Root/Building/Tenant/Form.js
  25. 3 1
      src/Screens/Root/Building/User/index.js
  26. 6 6
      src/Screens/Root/Contract/ConstructionPartner/Form.js
  27. 1 1
      src/Screens/Root/Contract/Management/Form.js
  28. 18 11
      src/Screens/Root/Energy/ManualMeter/Form.js
  29. 1 1
      src/Screens/Root/Equipment/Equipment/FormAddStock.js
  30. 1 1
      src/Screens/Root/Equipment/Return/Form.js
  31. 2 2
      src/Screens/Root/Etc/Announcement/Form.js
  32. 3 3
      src/Screens/Root/Etc/User/Form.js
  33. 1 1
      src/Screens/Root/Facility/BasicWorkSchedule/AnyWorkSchedule/Form.js
  34. 1 1
      src/Screens/Root/Facility/BasicWorkSchedule/ConstructWorkSchedule/Form.js
  35. 1 1
      src/Screens/Root/Facility/Common/EditWorkRequest.js
  36. 11 11
      src/Screens/Root/Facility/Complaint/Form.js
  37. 1 0
      src/Screens/Root/Facility/Investigation2/index.js
  38. 1 0
      src/Screens/Root/Facility/Investigation3/index.js
  39. 206 115
      src/Screens/Root/Facility/WorkHistory/Form.js
  40. 440 243
      src/Screens/Root/Facility/WorkProcess/Form.js
  41. 1 1
      src/Screens/Root/Material/Material/Form.js
  42. 2 2
      src/Screens/Root/Material/MaterialDailyStock/index.js
  43. 1 1
      src/Screens/Root/Material/MaterialMonthlyStock/index.js
  44. 2 2
      src/Screens/Root/Material/MaterialOrderStatusByStored/Form.js
  45. 16 21
      src/Screens/Root/Material/MaterialStored/Form.js
  46. 42 29
      src/Screens/Root/QRScan/index.js
  47. 5 0
      src/Screens/Root/Report/DailyReport/Form.js
  48. 548 230
      src/Screens/Root/Report/DailyReport/SubPages/BasicInfoForm.js
  49. 18 7
      src/Screens/Root/Report/ReportHistory/Form.js
  50. 160 108
      src/Utils/utils.js
  51. 1 1
      src/version.js
  52. 29 15
      yarn-error.log
  53. 54 19
      yarn.lock

+ 1 - 1
.vscode/settings.json

@@ -1,5 +1,5 @@
 {
-    "editor.formatOnSave": false,
+    "editor.formatOnSave": true,
     "editor.codeLens": true,
     "javascript.suggestionActions.enabled": false,
     "git.enableSmartCommit": false

+ 55 - 4
README.md

@@ -2,7 +2,7 @@
 
 ## 설치
 
-node.js 설치 (10.x 이상) - 10.x 설치권장(12.x 설치시 오류 발행하였음.)
+node.js 설치
 
 - <https://nodejs.org/>
 
@@ -54,26 +54,77 @@ React Native Debugger 설치
 - 4. 휴대폰 흔들기 메뉴 클릭(2번 눌러야 메뉴열림)
 - 5. 메뉴에서 Debug 실행
 - 6. React Native Debugger 에서 Ctrl+T 실행 하여 포트 선택후 확인
-- 이제 디버깅 됨.
+     (이제 디버깅 됨.)
  
 
 
 ## 환경설정
 
-/src/Config/index.js 파일
+/src/Config/index.js 파일 (운영환경) <br/>
+_Production Mode 및 배포하였을때 index.js 의 BASE_URL 및 WEB_URL 이 반영되어 실행됨._
 
 - /src/Config/index.js.example => /src/Config/index.js 로 복사
 
+/src/Config/index.development.js 파일 (개발환경) <br/>
+_Development Mode 에서 디버깅시 index.development.js 의 BASE_URL 및 WEB_URL 이 반영되어 실행됨._
+
+- /src/Config/index.development.js.example => /src/Config/index.development.js 로 복사
+
+/src/Config/index.development.js 파일 편집
+- BASE_URL 에 http://localhost:9090 => http://[본인내부IP]:9090 로 변경
+
 ```
 BASE_URL=http://[API주소]
 ```
 
+## 실행
+
+api.ezwork.kr 백앤드에 연결하여 실행
+
+- yarn start-cottus
+
+api.makething.co.kr 백앤드에 연결하여 실행
+
+- yarn start-fronnix
+
+api.i-fms.net 백앤드에 연결하여 실행
+
+- yarn start-hdc-icontrols
+
+/src/Config/index.development.js 파일의 BASE_URL 에 기입된 백앤드에 연결하여 실행
+
+- yarn start
+
+## 배포
+!! 배포전 yarn increase-version : 버전관리
+
+cottus(api.ezwork.kr) 계정에 배포 (내부테스트)
+- 1. yarn start-cottus 로 프로젝트 실행
+- 2. 새로운 Command Prompt 를 연다. (WinKey + R => cmd => Enter)
+- 3. 프로젝트 폴더로 이동.
+- 4. expo publish 로 배포시작 (오류가 발생할때가 있는데 expo publish 를 다시 하면 배포된다.)
+
+fronnix(api.makething.co.kr) 계정에 배포 (Icontrols 테스트)
+- 1. yarn start-fronnix 로 프로젝트 실행
+- 2. 새로운 Command Prompt 를 연다. (WinKey + R => cmd => Enter)
+- 3. 프로젝트 폴더로 이동.
+- 4. expo publish 로 배포시작 (오류가 발생할때가 있는데 expo publish 를 다시 하면 배포된다.)
+
+hdc-icontrols(api.i-fms.net) 계정에 배포 (운영)
+- 1. yarn start-hdc-icontrols 로 프로젝트 실행
+- 2. 새로운 Command Prompt 를 연다. (WinKey + R => cmd => Enter)
+- 3. 프로젝트 폴더로 이동.
+- 4. expo publish 로 배포시작 (오류가 발생할때가 있는데 expo publish 를 다시 하면 배포된다.)
+
 ## UI Components
 
+Expo
+- https://docs.expo.io
+
 React Native
 - https://facebook.github.io/react-native/docs/getting-started
 
-React Navigation
+React Navigation 4
 - https://reactnavigation.org/docs/en/getting-started.html
 
 Styled Component

+ 1 - 0
app.json

@@ -41,6 +41,7 @@
       "supportsTablet": true,
       "bundleIdentifier": "net.ifms.fms",
       "buildNumber": "1.0.3",
+      "usesIcloudStorage": true,
       "icon": "./assets/icon.png"
     },
     "android": {

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "main": "node_modules/expo/AppEntry.js",
   "scripts": {
-    "start-hdc-icontrols": "node scripts/screens.js && node scripts/svgs.js && node scripts/increase_version.js && node scripts/publish.js hdc-icontrols && expo login -u hdc-icontrols -p icontrols123., && expo start",
+    "start-hdc-icontrols": "node scripts/screens.js && node scripts/svgs.js && node scripts/publish.js hdc-icontrols && expo login -u hdc-icontrols -p icontrols123., && expo start",
     "start-fronnix": "node scripts/screens.js && node scripts/svgs.js && node scripts/publish.js fronnix && expo login -u fronnix -p 1999035 && expo start",
     "start-cottus": "node scripts/screens.js && node scripts/svgs.js && node scripts/publish.js cottus && expo login -u cottus -p insave11 && expo start",
     "start": "node scripts/screens.js && node scripts/svgs.js && expo start",

+ 0 - 2
scripts/version_push.bat

@@ -1,4 +1,2 @@
 git add src/version.js
 git commit -m "Version increased. %1 => %2"
-git pull -r
-git push

+ 1 - 3
src/App.js

@@ -27,8 +27,6 @@ import { CameraProvider } from './Components/UIControls/CameraProvider';
 import { PhoneProvider } from './Components/UIControls/Phone';
 import { DownloadProvider } from './Components/UIControls/Download';
 import * as Notifications from 'expo-notifications';
-import { enableScreens } from 'react-native-screens';
-enableScreens();
 
 const preloadedState = {};
 export const store = configureStore(preloadedState);
@@ -144,7 +142,7 @@ class App extends React.Component {
         <SplashProvider>
           {this.state.fontLoaded ? (
             <Provider store={store}>
-              <StatusBar translucent={true} barStyle="default" />
+              <StatusBar translucent={true} barStyle={Platform.OS == 'android' ? 'default' : 'dark-content'} />
               <SafeAreaView style={{ flex: 1, marginTop: Util.getStatusBarHeight(), backgroundColor:'#ffffff' }}>
                 <SearchProvider>
                   <PopupProvider>

+ 69 - 6
src/Components/Hooks/index.js

@@ -1,12 +1,12 @@
-import React, { useRef, useEffect } from 'react';
+import React, { useRef, useEffect, useState } from 'react';
 
 export const useAuth = (navigation) => {
-    const auth = navigation.getParam('auth', { Access:false, Update:false, Delete:false, Business:false });
-    const userinfo = navigation.getParam('userinfo', {BusinessFieldId:0, Name:'', SiteId:0, SiteName:'', UserGroupId:0, UserId:''});
-    const sitemap = navigation.getParam('sitemap', {name:'', auth:{}, path:'', icon:'', id:0, parentid:0});
+    const auth = navigation.getParam('auth', { Access: false, Update: false, Delete: false, Business: false });
+    const userinfo = navigation.getParam('userinfo', { BusinessFieldId: 0, Name: '', SiteId: 0, SiteName: '', UserGroupId: 0, UserId: '' });
+    const sitemap = navigation.getParam('sitemap', { name: '', auth: {}, path: '', icon: '', id: 0, parentid: 0 });
     const config = navigation.getParam('config', {});
     return { auth, userinfo, sitemap, config };
-}
+};
 
 export const usePrevious = (value) => {
     const ref = useRef();
@@ -14,4 +14,67 @@ export const usePrevious = (value) => {
         ref.current = value;
     }, [value]);
     return ref.current;
-}
+};
+
+export const useLayout = () => {
+    const ref = useRef(null);
+    const [layout, setLayout] = useState(null);
+    const [measure, setMeasure] = useState(null);
+    const complete = useRef(false);
+    const result = useRef({
+        ref: null,
+        layout: null,
+        measure: null,
+        onLayout: (event) => {},
+        isComplete: () => {
+            return false;
+        },
+        updateMeasure: updateMeasure,
+    });
+    const completeTimer = useRef(null);
+
+    result.current.ref = ref;
+    result.current.layout = layout;
+    result.current.measure = measure;
+    result.current.onLayout = (event) => {
+        console.log('onlayout');
+        const currlayout = { ...event.nativeEvent.layout };
+        setLayout(currlayout);
+        updateMeasure();
+    };
+    result.current.isComplete = () => {
+        return complete.current;
+    };
+    result.current.updateMeasure = updateMeasure;
+
+    const updateMeasure = () => {
+        console.log('update measure');
+        if (result.current.ref?.current?.measure) {
+            console.log('has measure');
+            result.current.ref.current.measure((x, y, width, height, pageX, pageY) => {
+                console.log('measure...');
+                if (
+                    measure?.x != x ||
+                    measure?.y != y ||
+                    measure?.pageX != pageX ||
+                    measure?.pageY != pageY ||
+                    measure?.width != width ||
+                    measure?.height != height
+                ) {
+                    complete.current = false;
+                    setMeasure({ x, y, width, height, pageX, pageY });
+                } else {
+                    complete.current = true;
+                }
+            });
+        }
+    };
+
+    useEffect(() => {
+        updateMeasure();
+    }, [result.current.ref.current]);
+
+    updateMeasure();
+
+    return result.current;
+};

+ 7 - 3
src/Components/Layouts/BottomTabBarLayout.js

@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState, forwardRef, useImperativeHandle, us
 import Styled from 'styled-components/native';
 import LottieView from 'lottie-react-native';
 import { getLottieColorFilters } from '~/Utils/lottie';
-import { Dimensions, View } from 'react-native';
+import { Dimensions, View, Platform } from 'react-native';
 import { useGestureHandlerRef } from 'react-navigation-stack';
 import Theme from '~/Themes';
 import { Svgs } from '~/Generated/Svgs';
@@ -155,7 +155,9 @@ const BottomTabBarLayout = forwardRef(({children, scroll=false}, ref) => {
                     }}
                     onMomentumScrollEnd={() => {
                         scrolling.current = false;
-                        dock();
+                        if(Platform.OS == 'android') {
+                            dock();
+                        }
                     }}
                     onScroll={(e) => {
                         const contentOffset = e.nativeEvent.contentOffset;
@@ -165,7 +167,9 @@ const BottomTabBarLayout = forwardRef(({children, scroll=false}, ref) => {
                         if(scrolling.current) {
                             if(pitch <= 5) {
                                 scrolling.current = false;
-                                dock();
+                                if(Platform.OS == 'android') {
+                                    dock();
+                                }
                             }
                         }
                     }}>

+ 24 - 22
src/Components/Layouts/PopupLayout.js

@@ -29,13 +29,15 @@ const ScrollContainer = Styled.ScrollView`
 `;
 
 class ActionProvider {
-    callAction = (action, parameter={}) => { console.log('default callAction - action : ', action) };
-    setCallActionListener = (handler=(action, parameter={})=>{}) => {
+    callAction = (action, parameter = {}) => {
+        console.log('default callAction - action : ', action);
+    };
+    setCallActionListener = (handler = (action, parameter = {}) => {}) => {
         this.callAction = handler;
-    }
-};
+    };
+}
 const contextParameter = {
-    action: new ActionProvider()
+    action: new ActionProvider(),
 };
 
 const LayoutContext = createContext(contextParameter);
@@ -43,37 +45,39 @@ const LayoutContext = createContext(contextParameter);
 export const useLayoutAction = () => {
     const layout = useContext(LayoutContext);
     console.log('useLayoutAction - return : ', layout.action.callAction);
-    return { callAction:layout.action.callAction }
-}
+    return { callAction: layout.action.callAction };
+};
 
-export const PopupLayout = ({children, title='', header=Fragment, headerProps={}, actionHandler=()=>{}, style={}}) => {
+export const PopupLayout = ({ children, title = '', header = Fragment, headerProps = {}, actionHandler = () => {}, style = {} }) => {
     const layout = useContext(LayoutContext);
     const [layoutState, setLayoutState] = useState(layout);
     const HeaderComponent = header;
 
     useEffect(() => {
-        console.log("layout change.. setCallActionListener");
-        layoutState.action.setCallActionListener((action, parameter={}) => {
+        console.log('layout change.. setCallActionListener');
+        layoutState.action.setCallActionListener((action, parameter = {}) => {
             actionHandler(action, parameter);
         });
         setLayoutState({
             ...layoutState,
         });
-    }, []);
+    }, [actionHandler]);
 
     return (
         <LayoutContext.Provider value={layoutState}>
             <Container>
                 {header != null && (
-                <HeaderContainer>
-                    <PopupHeader title={title}><HeaderComponent {...headerProps} /></PopupHeader>
-                </HeaderContainer>
+                    <HeaderContainer>
+                        <PopupHeader title={title}>
+                            <HeaderComponent {...headerProps} />
+                        </PopupHeader>
+                    </HeaderContainer>
                 )}
                 <Content style={[style]}>{children}</Content>
             </Container>
         </LayoutContext.Provider>
-    )
-}
+    );
+};
 
 const HeaderTitle = Styled.Text`
     flex: 1;
@@ -88,15 +92,13 @@ const ButtonContainer = Styled.View`
     flex-direction: row;
     padding-right: 15;
 `;
-export const PopupHeader = ({children, title=''}) => {
+export const PopupHeader = ({ children, title = '' }) => {
     const layout = useContext(LayoutContext);
 
     return (
         <Fragment>
             <HeaderTitle>{title}</HeaderTitle>
-            <ButtonContainer>
-                {children}
-            </ButtonContainer>
+            <ButtonContainer>{children}</ButtonContainer>
         </Fragment>
-    )
-}
+    );
+};

+ 1 - 1
src/Components/Splash/index.js

@@ -73,7 +73,7 @@ const Splash = ({visible=true}) => {
 
     return (
         !hide && loaded && (
-            <SplashContainer style={{opacity:opacityValue, transform:[{ translateX:position.x, translateY:position.y }]}}>
+            <SplashContainer style={{opacity:opacityValue, transform:[{ translateX:position.x }, { translateY:position.y }]}}>
                 <Image
                     style={{width:'100%', height:'100%'}}
                     source={require('./../../../assets/splash.png')}

+ 2 - 2
src/Components/UIControls/AnimatedContainer.js

@@ -165,9 +165,9 @@ export default AnimatedContainer = forwardRef(({children, visible, animation="sl
                 position: "absolute",
                 left: 0, top: 0, width: "100%", height: "100%",
                 backgroundColor:'black', opacity:fadeValue, 
-                transform:[{ translateX:backgroundPos.x, translateY: backgroundPos.y }] 
+                transform:[{ translateX:backgroundPos.x }, { translateY: backgroundPos.y }] 
             }} />
-            <Container style={{ transform:[{ translateX: animPos.x, translateY: animPos.y }], height:fullScreen?'100%':'auto' }}>
+            <Container style={{ transform:[{ translateX: animPos.x}, {translateY: animPos.y }], height:fullScreen?'100%':'auto' }}>
                 {scrollable ? (
                     <ContainerScroller>{children}</ContainerScroller>
                 ) : (

+ 17 - 6
src/Components/UIControls/ImageViewer.js

@@ -1,11 +1,12 @@
 import React, { useEffect, useState, useRef } from 'react';
 import Styled from 'styled-components/native';
-import { Image, ActivityIndicator, PixelRatio, ImageBackground } from 'react-native';
+import { Image, ActivityIndicator, PixelRatio, ImageBackground, Platform } from 'react-native';
 import WebView from 'react-native-webview';
 import { Util } from '~/Utils/utils';
 
 const Container = Styled.View`
     flex:1;
+    background-color:black;
 `;
 
 export const ImageViewer = ({source}) => {
@@ -24,19 +25,29 @@ export const ImageViewer = ({source}) => {
 
     return (
         <Container>
+            {Platform.OS === 'ios' ? (
             <WebView
                 originWhitelist={['*']}
-                source={{ uri: source.uri /*html: 
+                source={{ html: 
                     `<!DOCTYPE html>
                     <html style='width:100%; height:100%'>
                     <head></head>
-                    <body style='background-color:black;border:1px solid red'>
-                        <img src='https://api.i-fms.net/files/2/25089.jpg' style='width:100%' />
+                    <body style='background-color:black; width:100%; height:100%;'>
+                        <div style='display:flex; width:100%; height:100%; justify-content:center; align-items:center'>
+                            <img src='${source.uri}' style='width:100%' />
+                        </div>
                     </body>
-                    </html>` */
+                    </html>`
                 }}
-                style={{ flex:1, width:Util.getScreenWidth(), borderWidth:1, borderColor:'yellow' }}
+                style={{ flex:1, width:Util.getScreenWidth() }}
             />
+            ) : (
+            <WebView
+                originWhitelist={['*']}
+                source={{ uri: source.uri }}
+                style={{ flex:1, width:Util.getScreenWidth() }}
+            />
+            )}
             {loading && <ActivityIndicator size="large" color="white" style={{ position: 'absolute', alignSelf: 'center', alignContent: 'center' }} />}
         </Container>
     )

+ 52 - 1
src/Components/UIControls/Input.js

@@ -3,7 +3,7 @@ import Styled from 'styled-components/native';
 import Theme from '~/Themes';
 import { Util } from '~/Utils/utils';
 import { usePrevious } from '../Hooks';
-import { Text, TextInput } from 'react-native';
+import { Text, TextInput, Platform } from 'react-native';
 import { isTrue } from './Common';
 import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
 
@@ -98,6 +98,9 @@ export default Input = ({
     control=null,
     ...rest
 }) => {
+    const inputRef = useRef();
+    const inputCurrentText = useRef('');
+
     const toString = (value) => {
         if(typeof value === 'undefined') return value;
         if(value === null) return value;
@@ -132,8 +135,10 @@ export default Input = ({
             const value = textFilter(text);
             setInnerValue(value);
             onChangeText(value);
+            inputCurrentText.current = value;
         } else {
             onChangeText(text);
+            inputCurrentText.current = text;
         }
     }
 
@@ -173,9 +178,22 @@ export default Input = ({
     useEffect(() => {
         if(typeof prevDefaultValue !== 'undefined' && prevDefaultValue == '' && defaultValue !== '') {
             setInnerValue(toString(defaultValue));
+            if(!value && isValidFilter()) {
+                inputCurrentText.current = defaultValue;
+            }
         }
     }, [defaultValue]);
 
+    useEffect(() => {
+        try {
+            if(inputRef && inputRef.current && inputRef.current.setNativeProps) {
+                //inputRef.current.setNativeProps({ selection:{start:0,end:0 }});
+            }
+        } catch(error) {
+            console.error(error);
+        }
+    }, [inputRef.current]);
+
     return (
         innerEditable ? (
             <InputContainer style={[borderStyle, backgroundStyle, style, containerPadding]}>
@@ -189,6 +207,39 @@ export default Input = ({
                     value={value ? toString(value) : (isValidFilter() ? innerValue : null)}
                     multiline={multiline}
                     onChangeText={onChangeTextInterceptor}
+                    onFocus={() => {
+                        if(Platform.OS == 'android') {
+                            try {
+                                if(inputRef && inputRef.current && inputRef.current.setNativeProps) {
+                                    /*
+                                    inputRef.current.setNativeProps({ 
+                                        selection:{start:inputCurrentText.current.length,end:inputCurrentText.current.length }, 
+                                        text: inputCurrentText.current
+                                    });
+                                    */
+                                }
+                            } catch(error) {
+                                console.error(error);
+                            }
+                        }
+                    }}
+                    onBlur={() => {
+                        if(Platform.OS == 'android') {
+                            try {
+                                if(inputRef && inputRef.current && inputRef.current.setNativeProps) {
+                                    /*
+                                    inputRef.current.setNativeProps({ 
+                                        selection:{ start:0, end:0 }, 
+                                        text: inputCurrentText.current
+                                    });
+                                    */
+                                }
+                            } catch(error) {
+                                console.error(error);
+                            }
+                        }
+                    }}
+                    ref={inputRef}
                     {...rest}/>
             </InputContainer>
         ) : (

+ 1 - 1
src/Components/UIControls/Message.js

@@ -102,7 +102,7 @@ const MessageAnimatedContainer = ({children, message, index}) => {
     return (
         <MessageContainer style={{
             opacity:opacityValue,
-            transform:[{ translateX:positionValue.x, translateY: positionValue.y }] 
+            transform:[{ translateX:positionValue.x }, { translateY: positionValue.y }] 
         }}>{children}</MessageContainer>
     );
 }

+ 7 - 1
src/Components/UIControls/PopupSelect.js

@@ -24,14 +24,20 @@ export default PopupSelect = ({ navigation, path, popupProps = {}, style={}, emp
     const prevEditable = usePrevious(editable);
     const prevDefaultLabel = usePrevious(defaultLabel);
     useEffect(() => {
+        //console.log(`>>>> PopupSelect - useEffect[editable,defaultLabel]`);
         if(typeof prevEditable !== 'undefined' && prevEditable != editable) {
+            //console.log(`>>>> PopupSelect - useEffect - setData(${defaultLabel})`);
             setData({...data, label: defaultLabel});
         }
-        if((typeof prevDefaultLabel === 'undefined' || prevDefaultLabel == '') && !!defaultLabel) {
+        if((typeof prevDefaultLabel === 'undefined' || !prevDefaultLabel) && !!defaultLabel) {
+            //console.log(`>>>> PopupSelect - useEffect - setData(${defaultLabel})`);
             setData({...data, label: defaultLabel});
         }
     }, [editable, defaultLabel]);
 
+    //console.log(`>>>> PopupSelect - data : `);
+    //console.log(data);
+
     return (
         <SelectButton style={style}
             defaultLabel={emptyLabel} selectedLabel={data.label} editable={editable}

+ 16 - 16
src/Components/UIControls/UploadFile.js

@@ -487,8 +487,10 @@ const ProviderContainer = Styled.View`
     align-items: center;
 `;
 const ProviderContent = Styled.View`
-    margin-bottom: 50px;
-    width: 100%;
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    bottom: 50px;
     height: 200px;
     flex-direction: row;
     align-items: center;
@@ -548,20 +550,18 @@ export const UploadFileProvider = () => {
                     onSelect: payload.onSelect
                 });
             }} />
-            <ProviderContainer>
-                <ProviderContent>
-                    {payload.type == UploadFileType.Image && (
-                    <Item onPress={() => { payload.onSelect('camera'); showSelector({ showSelector: false, onSelect: payload.onSelect }); }}>
-                        <Icon iconFamily="AntDesign" iconName="camera" size={50} color="black" />
-                        <ItemText>사진촬영</ItemText>
-                    </Item>
-                    )}
-                    <Item onPress={() => { payload.onSelect('file'); showSelector({ showSelector: false, onSelect: payload.onSelect }); }}>
-                        <Icon iconFamily="AntDesign" iconName="file1" size={50} color="black" />
-                        <ItemText>파일선택</ItemText>
-                    </Item>
-                </ProviderContent>
-            </ProviderContainer>
+            <ProviderContent>
+                {payload.type == UploadFileType.Image && (
+                <Item onPress={() => { payload.onSelect('camera'); showSelector({ showSelector: false, onSelect: payload.onSelect }); }}>
+                    <Icon iconFamily="AntDesign" iconName="camera" size={50} color="black" />
+                    <ItemText>사진촬영</ItemText>
+                </Item>
+                )}
+                <Item onPress={() => { payload.onSelect('file'); showSelector({ showSelector: false, onSelect: payload.onSelect }); }}>
+                    <Icon iconFamily="AntDesign" iconName="file1" size={50} color="black" />
+                    <ItemText>파일선택</ItemText>
+                </Item>
+            </ProviderContent>
         </>
         )
     )

+ 394 - 0
src/Components/UIControls/dragdrop/index.tsx

@@ -0,0 +1,394 @@
+import React, { Component, createContext, useContext, useEffect, useRef, useState } from 'react';
+import {
+  Animated,
+  GestureResponderEvent,
+  LayoutChangeEvent,
+  PanResponder,
+  PanResponderGestureState,
+  PanResponderInstance,
+  StyleProp,
+  View,
+  ViewProps,
+  ViewStyle,
+} from 'react-native';
+
+export type TDropResult = {
+  dropX: number | null;
+  dropY: number | null;
+};
+
+const OPACITY_VISIBLE = 0.8;
+const OPACITY_HIDDEN = 0;
+
+const getMeasure = (component: React.RefObject<View>): Promise<TMeasureValue> => {
+  return new Promise((resolve, reject) => {
+    component.measure((x, y, width, height, pageX, pageY) => {
+      resolve({ x, y, width, height, pageX, pageY });
+    });
+  });
+};
+
+export interface DragDropProps extends ViewProps {
+  children: React.ReactNode;
+  hideWhenDrop?: boolean;
+  onDraggableCheck?: (e: GestureResponderEvent, gesture: PanResponderGestureState) => boolean;
+  onDragStart?: (e: GestureResponderEvent, gesture: PanResponderGestureState) => void;
+  onDragEnd?: (gesture: PanResponderGestureState) => TDropResult | null | undefined | boolean;
+  onRemove?: () => void;
+}
+
+export type TMeasureValue = {
+  x: number;
+  y: number;
+  width: number;
+  height: number;
+  pageX: number;
+  pageY: number;
+};
+
+export const DragDrop = ({
+  style,
+  children,
+  hideWhenDrop = true,
+  onDraggableCheck,
+  onDragStart,
+  onDragEnd,
+  onRemove,
+  ...props
+}: DragDropProps) => {
+  const dragDropContext = useContext(DragDropContext);
+  const global = useRef({ value: { x: 0, y: 0 } }).current;
+  const dragging = useRef<boolean>(false);
+  const ref = useRef<React.RefObject<View> | null>(null);
+  const measure = useRef<TMeasureValue | null>(null);
+
+  const onStartShouldSetPanResponder = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    dragging.current = !onDraggableCheck ? true : onDraggableCheck(e, gesture);
+    if (!dragging.current) return dragging.current;
+
+    if (dragDropContext.start && ref.current != null) {
+      dragging.current = true;
+    } else {
+      dragging.current = false;
+    }
+
+    return dragging.current;
+  };
+
+  const onPanResponderGrant = async (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    if (dragDropContext.start && ref.current != null) {
+      const measureValue: TMeasureValue = await getMeasure(ref.current);
+      measure.current = measureValue;
+      dragDropContext.start({
+        style,
+        children,
+        layoutStyle: {
+          left: measureValue.pageX,
+          top: measureValue.pageY,
+          width: measureValue.width,
+          height: measureValue.height,
+        },
+      });
+      dragDropContext.opacity.setValue(OPACITY_VISIBLE);
+    }
+
+    if (onDragStart) {
+      onDragStart(e, gesture);
+    }
+  };
+
+  const onPanResponderMove = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    if (!dragging.current) return;
+
+    dragDropContext.pan.setValue({
+      x: global.value.x + gesture.dx,
+      y: global.value.y + gesture.dy,
+    });
+  };
+
+  const moveToStartPosition = () => {
+    const identify = Math.random();
+    if (dragDropContext.endStart) dragDropContext.endStart(identify);
+
+    global.value = { x: 0, y: 0 };
+    Animated.timing(dragDropContext.pan, {
+      toValue: { x: global.value.x, y: global.value.y },
+      duration: 200,
+      useNativeDriver: true,
+    }).start(() => {
+      if (dragDropContext.endFinish) {
+        dragDropContext.opacity.setValue(OPACITY_HIDDEN);
+        dragDropContext.endFinish(identify);
+      }
+    });
+  };
+
+  const onPanResponderRelease = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    let dropResult: TDropResult | null | undefined | boolean = null;
+    if (!!onDragEnd) {
+      dropResult = onDragEnd(gesture);
+    }
+
+    if (!dragging.current) {
+      moveToStartPosition();
+      return;
+    }
+    dragging.current = false;
+
+    if (!!dropResult && !!measure.current) {
+      if (typeof dropResult === 'boolean') {
+        Animated.timing(dragDropContext.opacity, {
+          toValue: 0,
+          duration: 200,
+          useNativeDriver: true,
+        }).start(() => {
+          handleRemove();
+        });
+      } else {
+        if (dropResult?.dropX == null) {
+          global.value.x = global.value.x + gesture.dx;
+        } else {
+          global.value.x = dropResult.dropX - measure.current.pageX; // dropX 가 절대좌표이므로 toValue.x 에 상대좌표를 넣으려면 현 DragDrop 의 절대좌표 x 를 빼줘야 한다.
+        }
+        if (dropResult?.dropY == null) {
+          global.value.y = global.value.y + gesture.dy;
+        } else {
+          global.value.y = dropResult.dropY - measure.current.pageY; // dropY 가 절대좌표이므로 toValue.y 에 상대좌표를 넣으려면 현 DragDrop 의 절대좌표 y 를 빼줘야 한다.
+        }
+
+        Animated.timing(dragDropContext.pan, {
+          toValue: { x: global.value.x, y: global.value.y },
+          useNativeDriver: true,
+          duration: 200,
+        }).start(() => {
+          handleRemove();
+        });
+        if (hideWhenDrop) {
+          Animated.timing(dragDropContext.opacity, {
+            toValue: 0,
+            duration: 200,
+            useNativeDriver: true,
+          }).start();
+        }
+      }
+    } else {
+      moveToStartPosition();
+    }
+  };
+
+  const onPanResponderReject = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    console.log('reject');
+
+    if (dragDropContext.endStart && dragDropContext.endFinish) {
+      const identify = Math.random();
+      dragDropContext.endStart(identify);
+      dragDropContext.endFinish(identify);
+      dragDropContext.opacity.setValue(OPACITY_HIDDEN);
+    }
+
+    if (onDragEnd) onDragEnd(gesture);
+    moveToStartPosition();
+  };
+
+  const onPanResponderTerminate = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
+    console.log('terminate');
+
+    if (dragDropContext.endStart && dragDropContext.endFinish) {
+      const identify = Math.random();
+      dragDropContext.endStart(identify);
+      dragDropContext.endFinish(identify);
+      dragDropContext.opacity.setValue(OPACITY_HIDDEN);
+    }
+
+    if (onDragEnd) onDragEnd(gesture);
+    moveToStartPosition();
+  };
+
+  const createPanResponder = () => {
+    return PanResponder.create({
+      onStartShouldSetPanResponder: onStartShouldSetPanResponder,
+      onMoveShouldSetPanResponder: () => dragging.current,
+      onPanResponderGrant: onPanResponderGrant,
+      onPanResponderMove: onPanResponderMove,
+      onPanResponderRelease: onPanResponderRelease,
+      onPanResponderReject: onPanResponderReject,
+      onPanResponderTerminate: onPanResponderTerminate,
+    });
+  };
+
+  const [panResponder, setPanResponder] = useState<PanResponderInstance>(createPanResponder());
+
+  const handleRemove = () => {
+    if (dragDropContext.endStart && dragDropContext.endFinish) {
+      const identify = Math.random();
+      dragDropContext.endStart(identify);
+      dragDropContext.endFinish(identify);
+    }
+    if (onRemove) {
+      onRemove();
+    }
+  };
+
+  useEffect(() => {
+    dragDropContext.pan.setValue({ x: 0, y: 0 });
+    dragDropContext.pan.addListener((value) => {});
+  }, []);
+
+  useEffect(() => {
+    dragDropContext.pan.setValue({ x: 0, y: 0 });
+    global.value = { x: 0, y: 0 };
+    dragDropContext.opacity.setValue(OPACITY_VISIBLE);
+    setPanResponder(createPanResponder());
+  }, [onDragStart, onDragEnd, onRemove, hideWhenDrop, children]);
+
+  useEffect(() => {
+    setPanResponder(createPanResponder());
+  }, [dragDropContext]);
+
+  return (
+    <View {...props} {...panResponder.panHandlers} style={style} ref={ref}>
+      {children}
+    </View>
+  );
+};
+
+export type DragDropContextLayoutStyle = {
+  left: number;
+  top: number;
+  width: number;
+  height: number;
+};
+
+export type DragDropContextStartOptions = {
+  children?: React.ReactNode | null;
+  style?: StyleProp<ViewStyle>;
+  layoutStyle: DragDropContextLayoutStyle;
+};
+
+export type DragDropContextType = {
+  pan: Animated.ValueXY;
+  opacity: Animated.Value;
+  children?: React.ReactNode | null;
+  style?: StyleProp<ViewStyle>;
+  start?: (options: DragDropContextStartOptions) => void;
+  endStart?: (identify: number) => void;
+  endFinish?: (identify: number) => void;
+  endAnimationIdentify?: number;
+};
+const initialValue = {
+  pan: new Animated.ValueXY({ x: 0, y: 0 }),
+  opacity: new Animated.Value(0),
+  children: null,
+};
+export const DragDropContext = createContext<DragDropContextType>(initialValue);
+export type DragDropProviderProps = {
+  children?: React.ReactNode;
+};
+
+export const DragDropProvider = ({ children }: DragDropProviderProps) => {
+  const measure = useRef<TMeasureValue | null>(null);
+  const ref = useRef<React.RefObject<View> | null>(null);
+  const pan = useRef(new Animated.ValueXY({ x: 0, y: 0 })).current;
+  const opacity = useRef(new Animated.Value(0)).current;
+  const [rect, setRect] = useState({ left: 0, top: 0, width: 0, height: 0 });
+  const [show, setShow] = useState(false);
+
+  const start = async (options: DragDropContextStartOptions) => {
+    value.endAnimationIdentify = undefined;
+    setValue({ ...value, style: options.style, children: options.children, start, endStart, endFinish });
+    if (ref.current) {
+      measure.current = await getMeasure(ref.current);
+      if (
+        typeof options.layoutStyle.left !== 'undefined' &&
+        options.layoutStyle.left != null &&
+        typeof options.layoutStyle.top !== 'undefined' &&
+        options.layoutStyle.top != null &&
+        typeof options.layoutStyle.width !== 'undefined' &&
+        options.layoutStyle.width != null &&
+        typeof options.layoutStyle.height !== 'undefined' &&
+        options.layoutStyle.height != null
+      ) {
+        setRect({
+          left: options.layoutStyle.left - measure.current.pageX,
+          top: options.layoutStyle.top - measure.current.pageY,
+          width: options.layoutStyle.width,
+          height: options.layoutStyle.height,
+        });
+        setShow(true);
+      }
+    }
+  };
+
+  const endStart = (identify: number) => {
+    value.endAnimationIdentify = identify;
+  };
+
+  const endFinish = (identify: number) => {
+    if (value.endAnimationIdentify == identify) {
+      setShow(false);
+    }
+  };
+
+  const [value, setValue] = useState<DragDropContextType>({
+    pan: pan,
+    opacity: opacity,
+    children: null,
+    style: {},
+    start: start,
+    endStart: endStart,
+    endFinish: endFinish,
+  });
+
+  return (
+    <DragDropContext.Provider value={value}>
+      {children || null}
+      <View
+        style={[
+          value.style,
+          {
+            position: 'absolute',
+            marginLeft: 0,
+            marginTop: 0,
+            marginRight: 0,
+            marginBottom: 0,
+            left: 0,
+            top: 0,
+            width: 0,
+            height: 0,
+            opacity: 0,
+            overflow: 'hidden',
+          },
+        ]}
+        ref={ref}
+      />
+      {show && (
+        <>
+          <Animated.View
+            style={[
+              { transform: pan.getTranslateTransform(), opacity: opacity },
+              value.style,
+              { position: 'absolute', marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0, ...rect },
+            ]}
+          >
+            {value.children}
+          </Animated.View>
+          <Animated.View
+            style={[
+              { transform: pan.getTranslateTransform(), opacity: 0.3 },
+              value.style,
+              {
+                position: 'absolute',
+                backgroundColor: 'white',
+                marginLeft: 0,
+                marginTop: 0,
+                marginRight: 0,
+                marginBottom: 0,
+                ...rect,
+              },
+            ]}
+          />
+        </>
+      )}
+    </DragDropContext.Provider>
+  );
+};

+ 13 - 3
src/Screens/Drawer/index.js

@@ -7,7 +7,7 @@ import Theme from '~/Themes';
 import UserSvg from '~/Assets/Svgs/user.svg';
 import LockSvg from '~/Assets/Svgs/lock.svg';
 import Icon from '~/Components/UIControls/Icon';
-import { TouchableOpacity, View } from 'react-native';
+import { TouchableOpacity, View, UIManager, LayoutAnimation } from 'react-native';
 import session from '~/Utils/session';
 import { Svgs } from '~/Generated/Svgs';
 import { NavigationActions } from 'react-navigation';
@@ -69,6 +69,13 @@ const Body = Styled.ScrollView`
     flex: 1;
 `;
 
+if (
+    Platform.OS === "android" &&
+    UIManager.setLayoutAnimationEnabledExperimental
+) {
+    UIManager.setLayoutAnimationEnabledExperimental(true);
+}
+
 const MenuItem = ({depth=1, leaf=false, active=false, root=false, name="", menuid="", icon="", path="", auth={}, onActive=()=>{}, onNavigate=(path)=>{}}) => {
     const MenuIcon = Util.svg(active ?  "/icons/white" : "/icons/color", icon);
     
@@ -141,7 +148,7 @@ const MenuItem = ({depth=1, leaf=false, active=false, root=false, name="", menui
 const MenuElement = ({items, parent=null, depth = 1, navigation}) => {
 
     return (
-        <Fragment>
+        <View>
         {parent == null && (
             <MenuItem depth={1} leaf={true} root={true} name="대시보드" icon="dashboard"
                 onNavigate={() => {
@@ -158,6 +165,9 @@ const MenuElement = ({items, parent=null, depth = 1, navigation}) => {
                         name={menu.name} icon={menu.icon} menuid={menu.id} 
                         auth={menu.auth} path={menu.path}
                         onActive={() => {
+                            LayoutAnimation.configureNext(
+                                LayoutAnimation.create(150, LayoutAnimation.Types.easeInEaseOut, LayoutAnimation.Properties.opacity)
+                            );
                             setActive(!active);
                         }}
                         onNavigate={(path) => {
@@ -170,7 +180,7 @@ const MenuElement = ({items, parent=null, depth = 1, navigation}) => {
                 </Fragment>
             )
         })}
-        </Fragment>
+        </View>
     )
 };
 

+ 224 - 0
src/Screens/Independent/Popup/DragDropSample/index.js

@@ -0,0 +1,224 @@
+import React, { Fragment, useEffect, useRef, useState } from 'react';
+import { View, Text, TouchableOpacity, LayoutAnimation, Platform, UIManager, ScrollView, FlatList, StyleSheet } from 'react-native';
+import { PopupLayout, useLayoutAction } from '~/Components/Layouts/PopupLayout';
+import { SearchBoxIcon, DefaultButton, PrimaryButton } from '~/Components/Listing/Search';
+import { DefaultAction } from '~/Components/UIControls/Popup/Context';
+import { DragDrop, DragDropProvider } from '~/Components/UIControls/dragdrop';
+import Icon from '~/Components/UIControls/Icon';
+import { Util } from '~/Utils/utils';
+
+if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
+    UIManager.setLayoutAnimationEnabledExperimental(true);
+}
+
+const styles = StyleSheet.create({
+    container: {
+        flexDirection: 'row',
+        width: '100%',
+        height: '100%',
+    },
+    destination: {
+        backgroundColor: 'white',
+        borderRightWidth: 1,
+        borderColor: '#dedede',
+        width: '50%',
+    },
+    destitem: {
+        backgroundColor: '#ee4035',
+        padding: 10,
+        margin: 5,
+        flexDirection: 'row',
+        alignItems: 'center',
+        justifyContent: 'space-between',
+        borderRadius: 7,
+    },
+    destitemtext: {
+        color: 'white',
+        marginVertical: 5,
+    },
+    src: {
+        backgroundColor: 'white',
+        width: '50%',
+    },
+    srcitem: {
+        backgroundColor: '#005b96',
+        padding: 10,
+        margin: 5,
+        flexDirection: 'row',
+        alignItems: 'center',
+        borderRadius: 7,
+    },
+    srcitemtext: {
+        color: 'white',
+        marginVertical: 5,
+    },
+});
+
+export default Popup = ({ siteId = 0, popup = DefaultAction }) => {
+    const [items, setItems] = useState([]);
+    const [selectItems, setSelectItems] = useState([]);
+    const src = useRef();
+    const dest = useRef();
+    const destMeasure = useRef(null);
+    const lastSelectItem = useRef();
+    const lastSelectItemMeasure = useRef(null);
+
+    const updateMeasure = async () => {
+        destMeasure.current = await Util.getMeasure(dest.current);
+        if (lastSelectItem.current) {
+            lastSelectItemMeasure.current = await Util.getMeasure(lastSelectItem.current);
+        }
+    };
+
+    const handleDraggableCheck = (e, gesture) => {
+        if (e.nativeEvent.locationX <= 80) {
+            src.current.setNativeProps({ scrollEnabled: false });
+            updateMeasure();
+            return true;
+        } else {
+            src.current.setNativeProps({ scrollEnabled: true });
+            return false;
+        }
+    };
+
+    const handleDragStart = (e, gesture) => {};
+
+    const handleDragEnd = (gesture, item) => {
+        src.current.setNativeProps({ scrollEnabled: true });
+        if (selectItems.findIndex((value) => value.name == item.name) != -1) {
+            return false;
+        }
+
+        if (
+            !!destMeasure.current &&
+            gesture.moveX >= destMeasure.current.pageX &&
+            gesture.moveX <= destMeasure.current.pageX + destMeasure.current.width &&
+            gesture.moveY >= destMeasure.current.pageY &&
+            gesture.moveY <= destMeasure.current.pageY + destMeasure.current.height
+        ) {
+            if (selectItems.length > 0 && lastSelectItemMeasure.current) {
+                return {
+                    dropX: lastSelectItemMeasure.current.pageX,
+                    dropY: lastSelectItemMeasure.current.pageY + lastSelectItemMeasure.current.height,
+                };
+            } else {
+                return {
+                    dropX: destMeasure.current.pageX,
+                    dropY: destMeasure.current.pageY,
+                };
+            }
+        }
+        return false;
+    };
+
+    const appendSelected = (item) => {
+        if (selectItems.findIndex((value) => value.name == item.name) != -1) return;
+
+        LayoutAnimation.configureNext(LayoutAnimation.create(150, LayoutAnimation.Types.easeInEaseOut, LayoutAnimation.Properties.opacity));
+
+        setSelectItems([...selectItems, { name: item.name }]);
+    };
+
+    const removeSelected = (item) => {
+        const newItems = selectItems.filter((value) => value.name != item.name);
+
+        LayoutAnimation.configureNext(LayoutAnimation.create(150, LayoutAnimation.Types.easeInEaseOut, LayoutAnimation.Properties.opacity));
+
+        setSelectItems(newItems);
+    };
+
+    const actionHandler = (action, parameter = {}) => {
+        const actions = {
+            onClose: () => {
+                console.log('close...');
+                popup.close();
+            },
+            onSelect: () => {
+                console.log('select...');
+                const names = selectItems.map((item) => item.name).join(',');
+                popup.select(names);
+            },
+        };
+        actions[action]();
+    };
+
+    useEffect(() => {
+        let list = [];
+        for (let i = 1; i < 200; i++) {
+            list = [...list, { id: i, name: `이름${i}` }];
+        }
+        setItems(list);
+    }, []);
+
+    return (
+        <PopupLayout title="사용자 선택" header={Header} actionHandler={actionHandler}>
+            <View style={styles.container}>
+                <DragDropProvider>
+                    <View style={styles.destination} ref={dest}>
+                        <ScrollView style={{ width: '100%', height: '100%' }}>
+                            {selectItems.map((item, index) => {
+                                const last = selectItems.length - 1 == index;
+                                return (
+                                    <View key={`select-item-${index}`} style={styles.destitem} ref={last ? lastSelectItem : undefined}>
+                                        <Text style={styles.destitemtext}>{item.name}</Text>
+                                        <TouchableOpacity onPress={() => removeSelected(item)}>
+                                            <Icon iconFamily="AntDesign" iconName="minuscircle" size={20} color="white" />
+                                        </TouchableOpacity>
+                                    </View>
+                                );
+                            })}
+                        </ScrollView>
+                    </View>
+                    <FlatList
+                        style={[styles.src, { overflow: 'visible' }]}
+                        ref={src}
+                        data={items}
+                        keyExtractor={(item, index) => `item-${index}`}
+                        renderItem={({ item, index }) => {
+                            return (
+                                <DragDrop
+                                    style={styles.srcitem}
+                                    onDraggableCheck={handleDraggableCheck}
+                                    onDragStart={handleDragStart}
+                                    onDragEnd={(gesture) => {
+                                        return handleDragEnd(gesture, item);
+                                    }}
+                                    hideWhenDrop={true}
+                                    onRemove={() => {
+                                        appendSelected(item);
+                                    }}
+                                >
+                                    <Icon iconFamily="MaterialCommunityIcons" iconName="drag" size={20} color="white" />
+                                    <Text style={styles.srcitemtext}>{item.name}</Text>
+                                </DragDrop>
+                            );
+                        }}
+                    />
+                </DragDropProvider>
+            </View>
+        </PopupLayout>
+    );
+};
+
+const Header = () => {
+    const { callAction } = useLayoutAction();
+
+    return (
+        <Fragment>
+            <DefaultButton
+                onPress={() => {
+                    callAction('onClose');
+                }}
+            >
+                닫기
+            </DefaultButton>
+            <PrimaryButton
+                onPress={() => {
+                    callAction('onSelect');
+                }}
+            >
+                선택
+            </PrimaryButton>
+        </Fragment>
+    );
+};

+ 4 - 2
src/Screens/Independent/Popup/MaterialPurchaseOrder/index.js

@@ -102,7 +102,9 @@ class Item extends React.PureComponent {
 
 // list and search
 export default Popup = ({ siteId = 0, userinfo, auth, popup = DefaultAction }) => {
-    const [filters, setFilters] = useState({});
+    const [filters, setFilters] = useState({
+        'FmsMaterialPurchaseRequest.ProgressId_eq': { field: 'FmsMaterialPurchaseRequest.ProgressId', op: 'eq', value: '3' },
+    });
     const [list, setList] = useState(null);
     const [page, setPage] = useState(1);
     const [refreshing, setRefreshing] = useState(false);
@@ -184,7 +186,7 @@ export default Popup = ({ siteId = 0, userinfo, auth, popup = DefaultAction }) =
             </SearchListContainer>
 
             <Search
-                id="materialstock"
+                id="material-popup"
                 api={apiUrl}
                 page={page}
                 setPage={setPage}

+ 19 - 13
src/Screens/Independent/Popup/Scan/index.js

@@ -6,7 +6,7 @@ import { PopupLayout, useLayoutAction } from '~/Components/Layouts/PopupLayout';
 import { DefaultButton, ListStyle } from '~/Components/Listing/Search';
 import { DefaultAction } from '~/Components/UIControls/Popup/Context';
 
-export default Screen = ({popup=DefaultAction}) => {
+export default Screen = ({ popup = DefaultAction }) => {
     const [hasPermission, setHasPermission] = useState(null);
     const { showMessage } = useToast();
 
@@ -26,37 +26,43 @@ export default Screen = ({popup=DefaultAction}) => {
             onClose: () => {
                 popup.close();
             },
-        }
+        };
         actions[action]();
-    }
+    };
 
     let message = '';
-    if(hasPermission === null) {
+    if (hasPermission === null) {
         message = '카메라 접근권한을 허용해 주세요.';
     }
-    if(hasPermission === false) {
+    if (hasPermission === false) {
         message = '카메라 접근권한이 없습니다.';
     }
 
     return (
-        <PopupLayout title="QR코드 스캔" header={Header} headerProps={{callAction:actionHandler}} style={{ }}>
+        <EmptyLayout title="QR코드 스캔" header={Header} headerProps={{ callAction: actionHandler }} style={{}}>
             {hasPermission ? (
                 <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'flex-end' }}>
                     <BarCodeScanner onBarCodeScanned={handleBarCodeScanned} style={StyleSheet.absoluteFillObject} />
                 </View>
             ) : (
-                <View style={{ width:'100%', height:'100%', alignItems:'center', justifyContent:'center' }}>
-                    <Text style={[ListStyle.textMediumLarge, {fontSize:25, lineHeight:35}]}>{message}</Text>
+                <View style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center' }}>
+                    <Text style={[ListStyle.textMediumLarge, { fontSize: 25, lineHeight: 35 }]}>{message}</Text>
                 </View>
             )}
-        </PopupLayout>
+        </EmptyLayout>
     );
-}
+};
 
 const Header = ({ callAction }) => {
     return (
         <Fragment>
-            <DefaultButton onPress={() => { callAction('onClose') }}>닫기</DefaultButton>
+            <DefaultButton
+                onPress={() => {
+                    callAction('onClose');
+                }}
+            >
+                닫기
+            </DefaultButton>
         </Fragment>
-    )
-}
+    );
+};

+ 1 - 7
src/Screens/Login/index.js

@@ -378,13 +378,7 @@ const Login = (props) => {
                         LOGIN
                     </LoginButton>
                 </FormContainer>
-                <LogoText
-                    source={{
-                        uri: `${Config.BASE_URL}/files/static/app_login_logo.png?dummy=${dummy}`,
-                        headers: { Pragma: 'no-cache' },
-                        cache: 'reload',
-                    }}
-                />
+
                 <SystemName>Facility Management System</SystemName>
                 <Version>Ver. {version}</Version>
             </Container>

+ 3 - 1
src/Screens/Navigator.js

@@ -16,6 +16,7 @@ const LoginNavigator = createStackNavigator({
 });
 
 const mainStackNavigatorOptions = {
+    headerMode: 'screen',
     headerTitleAlign: 'center',
     initialRouteName: 'Index',
     defaultNavigationOptions: ({navigation}) => { 
@@ -32,11 +33,12 @@ const MainNavigator = createDrawerNavigator({
     Dashboard: createStackNavigator({
         Dashboard
     }, { 
+        headerMode: 'screen',
         headerTitleAlign: 'center',
         defaultNavigationOptions: ({navigation}) => { 
             return { 
                 header: () => <NavigationHeader navigation={navigation} />,
-                headerStyle: Platform.OS == "ios" ? { height: 50 } : {}
+                headerStyle: Platform.OS == "ios" ? { height: 50 } : {},
             } 
         }
     }),

+ 2 - 2
src/Screens/Root/Building/Tenant/Form.js

@@ -282,7 +282,7 @@ const Screen = ({navigation}) => {
                     <Form.Title style={{width:titleWidth}}><Form.Label>홈페이지</Form.Label></Form.Title>
                     <Form.Input placeholder="홈페이지" defaultValue={data.AddressZip} 
                                 onChangeText={text => setValue('AddressZip', text, true)} 
-                                editable={editable} returnKeyType="next" keyboardType="number-pad" />
+                                editable={editable} returnKeyType="next" />
                 </Form.Field>
                 <Form.Regist editable={editable} name="AddressZip" />
 
@@ -290,7 +290,7 @@ const Screen = ({navigation}) => {
                     <Form.Title style={{width:titleWidth}}><Form.Label>비고</Form.Label></Form.Title>
                     <Form.Input placeholder="비고" defaultValue={data.AddressZip} 
                                 onChangeText={text => setValue('AddressZip', text, true)} 
-                                editable={editable} returnKeyType="next" keyboardType="number-pad" />
+                                editable={editable} returnKeyType="next" />
                 </Form.Field>
                 <Form.Regist editable={editable} name="AddressZip" />
 

+ 3 - 1
src/Screens/Root/Building/User/index.js

@@ -108,7 +108,9 @@ const Item = ({item, index, onPress=()=>{}, showCallOrMessageSelector=()=>{}}) =
 // list and search
 const Screen = (props) => {
     const navigation = props.navigation;
-    const [filters, setFilters] = useState({});
+    const [filters, setFilters] = useState({
+        EmploymentStatus_ne:{field:'EmploymentStatus',op:'ne',value:3}
+    });
     const [list, setList] = useState(null);
     const [page, setPage] = useState(1);
     const [refreshing, setRefreshing] = useState(false);

+ 6 - 6
src/Screens/Root/Contract/ConstructionPartner/Form.js

@@ -22,9 +22,8 @@ const Screen = ({navigation}) => {
     const partnerId = navigation.getParam('partnerId', '');
     const { auth,config } = useAuth(navigation);
 
-    const [ready, setReady] = useState(false);
     const [loading, setLoading] = useState(false);
-    const [data, setData] = useState({});
+    const [data, setData] = useState({ IsUse: true });
     const { showMessage } = useToast();
 
     // mount
@@ -59,10 +58,12 @@ const Screen = ({navigation}) => {
             } catch(error) {
                 showMessage(error.message);
             }
+        } else {
+            const initialData = {IsUse:true};
+            setData(initialData);
+            Form.setFormData(initialData);
         }
 
-        setReady(false);
-        setReady(true);
         setLoading(false);
     }
 
@@ -133,7 +134,6 @@ const Screen = ({navigation}) => {
     console.log('UseServicePartner : ' +config.UseServicePartner);
     return ( 
         <BottomTabBarLayout>
-        {ready ? (
             <Form.Container onSave={handleSubmit(onSave)} onDelete={onDelete} onEdit={onEdit} onCancelEdit={onCancelEdit} loading={loading}>
                 <Form.Field>
                     <Form.Require style={{width:titleWidth}}><Form.Label>사업자번호</Form.Label></Form.Require>
@@ -263,7 +263,7 @@ const Screen = ({navigation}) => {
                 </Form.Field>
 
             </Form.Container>
-        ) : (
+        {loading && (
             <Form.Loading />
         )}
         </BottomTabBarLayout>

+ 1 - 1
src/Screens/Root/Contract/Management/Form.js

@@ -135,7 +135,7 @@ const Screen = ({navigation}) => {
                                 onChangeText={text => setValue('Name', text, true)} 
                                 editable={editable} returnKeyType="next" />
                 </Form.Field>
-                <Form.Regist editable={editable} name="Name" rule={{required:'사업자번호를 입력하세요.'}} error={errors.Name} />
+                <Form.Regist editable={editable} name="Name" rule={{required:'계약명을 입력하세요.'}} error={errors.Name} />
 
                 <Form.Field>
                     <Form.Title style={{width:titleWidth}}><Form.Label>계약날짜</Form.Label></Form.Title>

+ 18 - 11
src/Screens/Root/Energy/ManualMeter/Form.js

@@ -140,20 +140,27 @@ const Screen = ({navigation}) => {
                 CreatedDateTime: now + ` ${form.Hour}:00:00`,
             };
             console.log('submit data', submit);
-
-            try {
-                const result = await fetchPost('api/app/ManualMeter/Save', submit);
-
-                showMessage('저장되었습니다.');
-                refreshList();
-                fetchCurrentValue(now, data.Hour);
-            } catch(error) {
-                showMessage(error.message);
+            if(data.CurrentValue >= 0){
+                try {
+                    const result = await fetchPost('api/app/ManualMeter/Save', submit);
+
+                    showMessage('저장되었습니다.');
+                    refreshList();
+                    fetchCurrentValue(now, data.Hour);
+                } catch(error) {
+                    showMessage(error.message);
+                }
+            }else{
+                showMessage('검침값이 이전 검침값보다 작습니다.');
             }
             setLoading(false);
         });
     }
 
+    const calcCurrentValue = (currentPinValue, prevPinValue, multiple) => {
+        return Math.round((currentPinValue - prevPinValue) * multiple * 100) / 100;
+    }
+
     return ( 
         <BottomTabBarLayout>
             <Tab>
@@ -209,7 +216,7 @@ const Screen = ({navigation}) => {
                                     value={data.PrevPinValue} 
                                     defaultValue={data.PrevPinValue}
                                     onChangeText={(text) => {
-                                        const currentValue = data.CurrentPinValue == '' ? '0' : ((data.CurrentPinValue - Util.parseFloat(text)) * data.Multiple);
+                                        const currentValue = data.CurrentPinValue == '' ? '0' : calcCurrentValue(data.CurrentPinValue, Util.parseFloat(text), data.Multiple);
                                         setValue('PrevPinValue', text, true);
                                         setValue('CurrentValue', currentValue, true);
                                         setData({...data, PrevPinValue: text, CurrentValue: currentValue});
@@ -231,7 +238,7 @@ const Screen = ({navigation}) => {
                                     editable={editable} 
                                     value={data.CurrentPinValue} 
                                     onChangeText={(text) => {
-                                        const currentValue = text == '' ? '0' : ((Util.parseFloat(text) - data.PrevPinValue) * data.Multiple);
+                                        const currentValue = text == '' ? '0' : calcCurrentValue(Util.parseFloat(text), data.PrevPinValue, data.Multiple);
                                         setValue('CurrentPinValue', text, true);
                                         setValue('CurrentValue', currentValue, true);
                                         setData({...data, CurrentPinValue:text,CurrentValue:currentValue});

+ 1 - 1
src/Screens/Root/Equipment/Equipment/FormAddStock.js

@@ -93,7 +93,7 @@ const Screen = ({navigation}) => {
 
                 <Form.Field>
                     <Form.Require><Form.Label>공기구</Form.Label></Form.Require>
-                    <Form.EntitySelect entity="FmsEquipment"
+                    <Form.EntitySelect entity="FmsEquipment" siteId={siteId}
                         defaultLabel="공기구선택" editable={true}
                         onChange={(item) => {
                             setValue('EquipmentId', item.value, true);

+ 1 - 1
src/Screens/Root/Equipment/Return/Form.js

@@ -303,7 +303,7 @@ Screen.navigationOptions = ({navigation}) => {
                     <Fragment>
                     {auth.Delete && notApproval && (
                         <Fragment>
-                            <Form.DeleteButton type="primary" />
+                            <Form.DeleteButton />
                         </Fragment>
                     )}
                     {auth.Action1 && notApproval && (

+ 2 - 2
src/Screens/Root/Etc/Announcement/Form.js

@@ -178,10 +178,10 @@ const Screen = ({ navigation}) => {
               }}>무기한</Form.DefaultButton>
             )}
           </Form.Field>
-          <Form.Regist editable={editable} name="UpdateDate" />
+          <Form.Regist editable={editable} name="UpdateDate" rule={{required:'만료일을 선택하세요.'}} error={errors.UpdateDate} />
 
           <Form.Field>
-            <Form.Title><Form.Label>내용</Form.Label></Form.Title>
+            <Form.Require><Form.Label>내용</Form.Label></Form.Require>
             <Form.Input defaultValue={data.Contents} onChangeText={text => setValue('Contents', text, true)} 
                         multiline={true} editable={editable} />
           </Form.Field>

+ 3 - 3
src/Screens/Root/Etc/User/Form.js

@@ -169,7 +169,7 @@ const Screen = ({navigation}) => {
                                 editable={editable} returnKeyType="next" />
                 </Form.Field>
                 <Form.Regist editable={editable} name="UserId" rule={{required:'아이디를 입력하세요.'}} error={errors.UserId} />
-                {action == Form.EDIT && (
+                {action != Form.CREATE && editable && (
                     <Form.Field>
                     <Form.Title style={{width:titleWidth}}><Form.Label>비밀번호</Form.Label></Form.Title>
                     <Form.Input placeholder="입력 안할경우 변경 안됨" defaultValue={""} secureTextEntry={true}
@@ -244,7 +244,7 @@ const Screen = ({navigation}) => {
                 <Form.Regist editable={editable} name="UserGroupId" rule={{required:'권한그룹을 선택하세요.'}} error={errors.UserGroupId} />
 
                 <Form.Field>
-                    <Form.Title style={{width:titleWidth}}><Form.Label>고용형태</Form.Label></Form.Title>
+                    <Form.Require style={{width:titleWidth}}><Form.Label>고용형태</Form.Label></Form.Require>
                     <Selectbox style={{flex : 1}} initialValue={true} defaultLabel="고용형태"
                         items={employmentType.current}  editable={editable} selectedValue={data.EmploymentType}
                         onChange={item => {
@@ -254,7 +254,7 @@ const Screen = ({navigation}) => {
                 <Form.Regist editable={editable} name="EmploymentType"  />
 
                 <Form.Field>
-                    <Form.Title style={{width:titleWidth}}><Form.Label>근무상태</Form.Label></Form.Title>
+                    <Form.Require style={{width:titleWidth}}><Form.Label>근무상태</Form.Label></Form.Require>
                     <Selectbox style={{flex : 1}} initialValue={true} defaultLabel="근무상태"
                         items={employmentStatus.current}  editable={editable} selectedValue={data.EmploymentStatus}
                         onChange={item => {

+ 1 - 1
src/Screens/Root/Facility/BasicWorkSchedule/AnyWorkSchedule/Form.js

@@ -315,7 +315,7 @@ Screen.navigationOptions = ({navigation}) => {
                     {!editable && (
                         <Fragment>
                             {auth.Update && <Form.EditButton navigation={navigation} type="primary" />}
-                            {auth.Delete && <Form.DeleteButton navigation={navigation} type="primary" />}
+                            {auth.Delete && <Form.DeleteButton navigation={navigation} />}
                         </Fragment>
                     )}
                     {editable && (

+ 1 - 1
src/Screens/Root/Facility/BasicWorkSchedule/ConstructWorkSchedule/Form.js

@@ -313,7 +313,7 @@ Screen.navigationOptions = ({navigation}) => {
                     {!editable && (
                         <Fragment>
                             {auth.Update && <Form.EditButton navigation={navigation} type="primary" />}
-                            {auth.Delete && <Form.DeleteButton navigation={navigation} type="primary" />}
+                            {auth.Delete && <Form.DeleteButton navigation={navigation} />}
                         </Fragment>
                     )}
                     {editable && (

+ 1 - 1
src/Screens/Root/Facility/Common/EditWorkRequest.js

@@ -332,7 +332,7 @@ Screen.navigationOptions = ({navigation}) => {
                     {!readonly && !editable && (
                         <Fragment>
                             {auth.Update && <Form.EditButton navigation={navigation} type="primary" />}
-                            {auth.Delete && <Form.DeleteButton navigation={navigation} type="primary" />}
+                            {auth.Delete && <Form.DeleteButton navigation={navigation} />}
                         </Fragment>
                     )}
                     {!readonly && editable && (

+ 11 - 11
src/Screens/Root/Facility/Complaint/Form.js

@@ -397,19 +397,19 @@ Screen.navigationOptions = ({ navigation }) => {
                 main={false}
                 buttons={
                     <Fragment>
-                        <Form.PrimaryButton
-                            buttonStyle={{ width:60 }}
-                            onPress={() => {
-                                navigation.navigate('PrintForm', {
-                                    siteId: siteId,
-                                    complaintId: complaintId,
-                                });
-                            }}
-                        >
-                            리포트
-                        </Form.PrimaryButton>
                         {!editable && (
                             <Fragment>
+                                <Form.PrimaryButton
+                                    buttonStyle={{ width:60 }}
+                                    onPress={() => {
+                                        navigation.navigate('PrintForm', {
+                                            siteId: siteId,
+                                            complaintId: complaintId,
+                                        });
+                                    }}
+                                >
+                                    리포트
+                                </Form.PrimaryButton>
                                 {auth.Update && <Form.EditButton navigation={navigation} buttonStyle={{ width:50 }} type="primary" />}
                                 {auth.Delete && <Form.DeleteButton buttonStyle={{ width:50 }} />}
                             </Fragment>

+ 1 - 0
src/Screens/Root/Facility/Investigation2/index.js

@@ -16,6 +16,7 @@ import Input from '~/Components/UIControls/Input';
 import Form from '~/Components/Form';
 import { Util } from '~/Utils/utils';
 import { useAuth } from '~/Components/Hooks';
+import { Selectbox } from '~/Components/UIControls/Selectbox';
 
 // list item
 const Item = ({ item, index, onPress = () => { } }) => {

+ 1 - 0
src/Screens/Root/Facility/Investigation3/index.js

@@ -16,6 +16,7 @@ import Input from '~/Components/UIControls/Input';
 import Form from '~/Components/Form';
 import { Util } from '~/Utils/utils';
 import { useAuth } from '~/Components/Hooks';
+import { Selectbox } from '~/Components/UIControls/Selectbox';
 
 // list item
 const Item = ({ item, index, onPress = () => { } }) => {

+ 206 - 115
src/Screens/Root/Facility/WorkHistory/Form.js

@@ -21,9 +21,9 @@ import { UploadFileType } from '~/Components/UIControls/UploadFile';
 
 const titleWidth = 100;
 
-// 작업이력 관리 
-const Screen = ({navigation}) => {
-    const refreshList = navigation.getParam('refreshList', ()=>{});
+// 작업이력 관리
+const Screen = ({ navigation }) => {
+    const refreshList = navigation.getParam('refreshList', () => {});
     const siteId = navigation.getParam('siteId', '');
     const workRequestId = navigation.getParam('workRequestId', 0);
     const tab = navigation.getParam('tab', 'info');
@@ -43,9 +43,8 @@ const Screen = ({navigation}) => {
     }, []);
 
     // unmount
-    useEffect(() => () => {
-    }, []);
-    
+    useEffect(() => () => {}, []);
+
     // react hook form initialize
     const { register, setValue, handleSubmit, errors, getValues, control } = useForm();
     useLayoutEffect(() => {
@@ -62,186 +61,252 @@ const Screen = ({navigation}) => {
             setFacilities(result.FmsWorkRequestToFacility);
             setAccidents(result.FmsWorkRequestToAccident);
             setComplaints(result.FmsWorkRequestToComplaint);
-        } catch(error) {
+        } catch (error) {
             showMessage(error.message);
         }
 
         setLoading(false);
-    }
+    };
 
     // delete
     const onDelete = () => {
-        confirm('삭제','삭제하시겠습니까?', async () => {
+        confirm('삭제', '삭제하시겠습니까?', async () => {
             try {
                 await fetchDelete(`api/app/WorkResult/${siteId}/${workRequestId}`);
 
                 showMessage('삭제되었습니다.');
                 refreshList();
                 navigation.pop();
-            } catch(error) {
+            } catch (error) {
                 console.log(error.message);
                 showMessage(error.message);
             }
         });
-    }
+    };
 
     const refresh = async () => {
         refreshList();
         fetch();
-    }
+    };
 
-    return ( 
+    return (
         <BottomTabBarLayout>
             <Fragment>
                 <Tab>
                     <TabHeader>
                         <TabTitleGroup top={true}>
-                            <TabTitle onPress={() => {
-                                navigation.setParams({ tab: 'info' });
-                            }} active={tab=='info'?true:false} title="작업지시내용" />
-                            <TabTitle onPress={() => {
-                                navigation.setParams({ tab: 'facilities' });
-                            }} active={tab=='facilities'?true:false} title="시설목록" />
+                            <TabTitle
+                                onPress={() => {
+                                    navigation.setParams({ tab: 'info' });
+                                }}
+                                active={tab == 'info' ? true : false}
+                                title="작업지시내용"
+                            />
+                            <TabTitle
+                                onPress={() => {
+                                    navigation.setParams({ tab: 'facilities' });
+                                }}
+                                active={tab == 'facilities' ? true : false}
+                                title="시설목록"
+                            />
                         </TabTitleGroup>
                         <TabTitleGroup>
-                            <TabTitle onPress={() => {
-                                navigation.setParams({ tab: 'history' });
-                            }} active={tab=='history'?true:false} title="작업이력" />
+                            <TabTitle
+                                onPress={() => {
+                                    navigation.setParams({ tab: 'history' });
+                                }}
+                                active={tab == 'history' ? true : false}
+                                title="작업이력"
+                            />
                             {accidents && accidents.length > 0 && (
-                                <TabTitle onPress={() => {
-                                    navigation.setParams({ tab: 'accidents' });
-                                }} active={tab=='accidents'?true:false} title="사고목록" />
+                                <TabTitle
+                                    onPress={() => {
+                                        navigation.setParams({ tab: 'accidents' });
+                                    }}
+                                    active={tab == 'accidents' ? true : false}
+                                    title="사고목록"
+                                />
                             )}
                             {complaints && complaints.length > 0 && (
-                                <TabTitle onPress={() => {
-                                    navigation.setParams({ tab: 'complaints' });
-                                }} active={tab=='complaints'?true:false} title="민원목록" />
+                                <TabTitle
+                                    onPress={() => {
+                                        navigation.setParams({ tab: 'complaints' });
+                                    }}
+                                    active={tab == 'complaints' ? true : false}
+                                    title="민원목록"
+                                />
                             )}
-                            <TabTitle onPress={() => {
-                                navigation.setParams({ tab: 'material' });
-                            }} active={tab=='material'?true:false} title="자재목록" />
+                            <TabTitle
+                                onPress={() => {
+                                    navigation.setParams({ tab: 'material' });
+                                }}
+                                active={tab == 'material' ? true : false}
+                                title="자재목록"
+                            />
                         </TabTitleGroup>
                     </TabHeader>
                     <TabContent>
-                        <TabItem active={tab=='info'?true:false}>
+                        <TabItem active={tab == 'info' ? true : false}>
                             <Form.Container id="history-manage-form" onDelete={onDelete}>
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>지시제목</Form.Label></Form.Title>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>지시제목</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        control={control}
                                         name="Title"
-                                        as={
-                                            <Form.Input defaultValue={Util.get(data, "Title")} editable={false} />
-                                        }
+                                        as={<Form.Input defaultValue={Util.get(data, 'Title')} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>작업상태</Form.Label></Form.Title>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>작업상태</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        control={control}
                                         name="WorkProgress.Name"
-                                        as={
-                                            <Form.Input defaultValue={Util.get(data, "WorkProgress.Name")} editable={false} />
-                                        }
+                                        as={<Form.Input defaultValue={Util.get(data, 'WorkProgress.Name')} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>작업예정일</Form.Label></Form.Title>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>작업예정일</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        control={control}
                                         name="StartWorkDate"
-                                        as={
-                                            <Form.Input defaultValue={Util.getDateString(data, "StartWorkDate")} editable={false} />
-                                        }
+                                        as={<Form.Input defaultValue={Util.getDateString(data, 'StartWorkDate')} editable={false} />}
                                     />
                                 </Form.Field>
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label></Form.Label></Form.Title>
-                                    <Controller name="WorkEndDate" control={control}
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label></Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        name="WorkEndDate"
+                                        control={control}
                                         as={<Form.DatePicker date={data.WorkEndDate} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>작업일시</Form.Label></Form.Title>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>작업일시</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        control={control}
                                         name="FmsWorkResult.StartDate"
                                         as={
-                                            <Form.Input defaultValue={Util.getDateTimeString(data, "FmsWorkResult.StartDate")} editable={false} />
+                                            <Form.Input
+                                                defaultValue={Util.getDateTimeString(data, 'FmsWorkResult.StartDate')}
+                                                editable={false}
+                                            />
                                         }
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label></Form.Label></Form.Title>
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label></Form.Label>
+                                    </Form.Title>
                                     <Controller
                                         control={control}
                                         name="FmsWorkResult.EndDate"
                                         as={
-                                            <Form.Input defaultValue={Util.getDateTimeString(data, "FmsWorkResult.EndDate")} editable={false} />
+                                            <Form.Input
+                                                defaultValue={Util.getDateTimeString(data, 'FmsWorkResult.EndDate')}
+                                                editable={false}
+                                            />
                                         }
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>작업자</Form.Label></Form.Title>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>작업자</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        control={control}
                                         name="FmsWorkResult.WorkerUserName"
                                         as={
-                                            <Form.Input defaultValue={Util.get(data, "FmsWorkResult.WorkerUserName")} editable={false} />
+                                            <Form.Input
+                                                defaultValue={
+                                                    Util.get(data, 'FmsWorkResult.WorkerUserName') +
+                                                    (Util.get(data, 'WorkUsers') != null ? ' - ' + Util.get(data, 'WorkUsers') : '')
+                                                }
+                                                editable={false}
+                                            />
                                         }
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>업체명</Form.Label></Form.Title>
-                                    <Controller name="WorkPartnerName" control={control}
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>업체명</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        name="WorkPartnerName"
+                                        control={control}
                                         as={<Form.Input defaultValue={data.WorkPartnerName} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.Title style={{width:titleWidth}}><Form.Label>금액</Form.Label></Form.Title>
-                                    <Controller name="WorkPrice" control={control}
+                                    <Form.Title style={{ width: titleWidth }}>
+                                        <Form.Label>금액</Form.Label>
+                                    </Form.Title>
+                                    <Controller
+                                        name="WorkPrice"
+                                        control={control}
                                         as={<Form.Input defaultValue={data.WorkPrice} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 <Form.Field>
-                                    <Form.TitleTop style={{width:titleWidth}}><Form.Label>신청내용</Form.Label></Form.TitleTop>
-                                    <Controller 
-                                        control={control} 
+                                    <Form.TitleTop style={{ width: titleWidth }}>
+                                        <Form.Label>신청내용</Form.Label>
+                                    </Form.TitleTop>
+                                    <Controller
+                                        control={control}
                                         name="Content"
-                                        as={
-                                            <Form.Input defaultValue={Util.get(data, "Content")} multiline={true} editable={false} />
-                                        }
+                                        as={<Form.Input defaultValue={Util.get(data, 'Content')} multiline={true} editable={false} />}
                                     />
                                 </Form.Field>
 
                                 {!config.UseWorkAutoOrder && (
                                     <Fragment>
                                         <Form.Field>
-                                            <Form.TitleTop style={{width:titleWidth}}><Form.Label>지시내용</Form.Label></Form.TitleTop>
-                                            <Controller 
-                                                control={control} 
+                                            <Form.TitleTop style={{ width: titleWidth }}>
+                                                <Form.Label>지시내용</Form.Label>
+                                            </Form.TitleTop>
+                                            <Controller
+                                                control={control}
                                                 name="FmsWorkOrder.Content"
                                                 as={
-                                                    <Form.Input defaultValue={Util.get(data, "FmsWorkOrder.Content")} multiline={true} editable={false} />
+                                                    <Form.Input
+                                                        defaultValue={Util.get(data, 'FmsWorkOrder.Content')}
+                                                        multiline={true}
+                                                        editable={false}
+                                                    />
                                                 }
                                             />
                                         </Form.Field>
 
                                         <Form.Field>
-                                            <Form.TitleTop style={{width:titleWidth}}><Form.Label>작업요약</Form.Label></Form.TitleTop>
-                                            <Controller 
-                                                control={control} 
+                                            <Form.TitleTop style={{ width: titleWidth }}>
+                                                <Form.Label>작업요약</Form.Label>
+                                            </Form.TitleTop>
+                                            <Controller
+                                                control={control}
                                                 name="FmsWorkResult.Content"
                                                 as={
-                                                    <Form.Input defaultValue={Util.get(data, "FmsWorkResult.Content")} multiline={true} editable={false} />
+                                                    <Form.Input
+                                                        defaultValue={Util.get(data, 'FmsWorkResult.Content')}
+                                                        multiline={true}
+                                                        editable={false}
+                                                    />
                                                 }
                                             />
                                         </Form.Field>
@@ -250,57 +315,83 @@ const Screen = ({navigation}) => {
 
                                 {data.WorkProgressId == 6 && (
                                     <Form.Field>
-                                        <Form.TitleTop style={{width:titleWidth}}><Form.Label>승인내역</Form.Label></Form.TitleTop>
-                                        <Controller 
-                                            control={control} 
+                                        <Form.TitleTop style={{ width: titleWidth }}>
+                                            <Form.Label>승인내역</Form.Label>
+                                        </Form.TitleTop>
+                                        <Controller
+                                            control={control}
                                             name="FmsWorkResult.ConfirmDesc"
                                             as={
-                                                <Form.Input defaultValue={Util.get(data, "FmsWorkResult.ConfirmDesc")} multiline={true} editable={false} />
+                                                <Form.Input
+                                                    defaultValue={Util.get(data, 'FmsWorkResult.ConfirmDesc')}
+                                                    multiline={true}
+                                                    editable={false}
+                                                />
                                             }
                                         />
                                     </Form.Field>
                                 )}
 
                                 <Form.Field>
-                                    <Form.TitleTop style={{width:titleWidth}}><Form.Label>첨부파일</Form.Label></Form.TitleTop>
-                                    <Controller name="CmFile" control={control}
+                                    <Form.TitleTop style={{ width: titleWidth }}>
+                                        <Form.Label>첨부파일</Form.Label>
+                                    </Form.TitleTop>
+                                    <Controller
+                                        name="CmFile"
+                                        control={control}
                                         as={<Form.UploadFile type={UploadFileType.Image} editable={false} defaultFile={data.CmFile} />}
                                     />
                                 </Form.Field>
 
-                                <Form.Field style={{ height:30 }}>
-                                </Form.Field>
+                                <Form.Field style={{ height: 30 }}></Form.Field>
                             </Form.Container>
                         </TabItem>
-                        <TabItem active={tab=='facilities'?true:false}>
-                            <Facilities navigation={navigation} 
-                                keys={{SiteId:siteId, WorkRequestId: workRequestId}}
-                                facilities={facilities} setFacilities={setFacilities} editable={false} />
+                        <TabItem active={tab == 'facilities' ? true : false}>
+                            <Facilities
+                                navigation={navigation}
+                                keys={{ SiteId: siteId, WorkRequestId: workRequestId }}
+                                facilities={facilities}
+                                setFacilities={setFacilities}
+                                editable={false}
+                            />
                         </TabItem>
-                        <TabItem active={tab=='history'?true:false} lazy={true}>
-                            <WorkHistory siteId={siteId} workRequestId={workRequestId} 
-                                startDate={Util.getDateString(data, "FmsWorkResult.StartDate")} 
-                                endDate={Util.getDateString(data, "FmsWorkResult.EndDate")} 
-                                editable={false} creatable={false} auth={auth} 
+                        <TabItem active={tab == 'history' ? true : false} lazy={true}>
+                            <WorkHistory
+                                siteId={siteId}
+                                workRequestId={workRequestId}
+                                startDate={Util.getDateString(data, 'FmsWorkResult.StartDate')}
+                                endDate={Util.getDateString(data, 'FmsWorkResult.EndDate')}
+                                editable={false}
+                                creatable={false}
+                                auth={auth}
                                 onCallback={(action) => {
                                     refresh();
-                                }} />
+                                }}
+                            />
                         </TabItem>
                         {accidents && accidents.length > 0 && (
-                            <TabItem active={tab=='accidents'?true:false}>
-                                <Accidents navigation={navigation} 
-                                    keys={{SiteId:siteId, WorkRequestId: workRequestId}}
-                                    accidents={accidents} setAccidents={setAccidents} editable={false} />
+                            <TabItem active={tab == 'accidents' ? true : false}>
+                                <Accidents
+                                    navigation={navigation}
+                                    keys={{ SiteId: siteId, WorkRequestId: workRequestId }}
+                                    accidents={accidents}
+                                    setAccidents={setAccidents}
+                                    editable={false}
+                                />
                             </TabItem>
                         )}
                         {complaints && complaints.length > 0 && (
-                            <TabItem active={tab=='complaints'?true:false}>
-                                <Complaints navigation={navigation} 
-                                    keys={{SiteId:siteId, WorkRequestId: workRequestId}}
-                                    complaints={complaints} setComplaints={setComplaints} editable={false} />
+                            <TabItem active={tab == 'complaints' ? true : false}>
+                                <Complaints
+                                    navigation={navigation}
+                                    keys={{ SiteId: siteId, WorkRequestId: workRequestId }}
+                                    complaints={complaints}
+                                    setComplaints={setComplaints}
+                                    editable={false}
+                                />
                             </TabItem>
                         )}
-                        <TabItem active={tab=='material'?true:false} alwaysReload={true}>
+                        <TabItem active={tab == 'material' ? true : false} alwaysReload={true}>
                             <Materials siteId={siteId} workRequestId={workRequestId} />
                         </TabItem>
                     </TabContent>
@@ -311,14 +402,14 @@ const Screen = ({navigation}) => {
     );
 };
 
-Screen.navigationOptions = ({navigation}) => { 
+Screen.navigationOptions = ({ navigation }) => {
     const readonly = navigation.getParam('readonly', false);
     const { auth } = useAuth(navigation);
 
-    return { 
+    return {
         header: () => (
-            <Header 
-                navigation={navigation} 
+            <Header
+                navigation={navigation}
                 title={`이력관리`}
                 main={false}
                 buttons={
@@ -326,9 +417,9 @@ Screen.navigationOptions = ({navigation}) => {
                         {!readonly && auth.Update && <Form.DeleteButton id="history-manage-form" navigation={navigation} />}
                     </Fragment>
                 }
-            /> 
-        )
-    } 
+            />
+        ),
+    };
 };
 
-export default Screen;
+export default Screen;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 440 - 243
src/Screens/Root/Facility/WorkProcess/Form.js


+ 1 - 1
src/Screens/Root/Material/Material/Form.js

@@ -386,7 +386,7 @@ const Screen = ({ navigation }) => {
                     </Form.Field>
 
                     {/* QR코드 // input */}
-                    <Form.Field>
+                    <Form.Field style={{display:'none'}}>
                         <Form.Title>
                             <Form.Label>QR코드</Form.Label>
                         </Form.Title>

+ 2 - 2
src/Screens/Root/Material/MaterialDailyStock/index.js

@@ -218,12 +218,12 @@ const Screen = (props) => {
 
             <Search
                 id="material_dailystock"
-                api={`api/app/MaterialDailyStock?siteId=${session.getSiteId()}&businessAuth=${auth.Business}`}
+                api={`api/MaterialDailyStock?siteId=${session.getSiteId()}&businessAuth=${auth.Business}`}
                 page={page}
                 setPage={setPage}
                 limit={50}
                 filters={filters}
-                sort={{ field: 'Date', order: 'desc' }}
+                sort={{ field: 'SDate', order: 'asc' }}
                 onStart={start}
                 onSuccess={success}
                 onFailure={fail}

+ 1 - 1
src/Screens/Root/Material/MaterialMonthlyStock/index.js

@@ -218,7 +218,7 @@ const Screen = (props) => {
 
             <Search
                 id="material_dailystock"
-                api={`api/app/MaterialMonthlyStock?siteId=${session.getSiteId()}`}
+                api={`api/MaterialMonthlyStock?siteId=${session.getSiteId()}`}
                 page={page}
                 setPage={setPage}
                 limit={50}

+ 2 - 2
src/Screens/Root/Material/MaterialOrderStatusByStored/Form.js

@@ -150,7 +150,7 @@ const Screen = ({ navigation }) => {
         confirm('저장', '정말 입고처리 하시겠습니까?', async () => {
             setLoading(true);
             try {
-                const result = await fetchPost(`api/MaterialOrderStatusByStored/${id[0]}/${id[1]}/${id[2]}`, {});
+                const result = await fetchPost(`api/MaterialOrderStatusByStored/${id[0]}/${id[1]}/${id[2]}/${auth.Business}`, {});
                 showMessage('입고되었습니다.');
                 refreshList();
                 navigation.pop();
@@ -339,7 +339,7 @@ Screen.navigationOptions = ({ navigation }) => {
         header: () => (
             <Header
                 navigation={navigation}
-                title={`구매 발주 정보`}
+                title={`미입고현황`}
                 main={false}
                 buttons={
                     <Form.PrimaryButton onPress={handler} buttonStyle={{ backgroundColor: '#0EB118', borderColor: '#0EB118' }}>

+ 16 - 21
src/Screens/Root/Material/MaterialStored/Form.js

@@ -106,7 +106,11 @@ const Screen = ({ navigation }) => {
 
     const [loading, setLoading] = useState(false);
     const { auth, userinfo, config } = useAuth(navigation);
-    const [data, setData] = useState({ StoredDate:moment().format('YYYY-MM-DD HH:mm:ss'), FmsMaterialPurchaseOrder: {}, FmsMaterialWarehouse: {} });
+    const [data, setData] = useState({
+        StoredDate: moment().format('YYYY-MM-DD HH:mm:ss'),
+        FmsMaterialPurchaseOrder: {},
+        FmsMaterialWarehouse: {},
+    });
     const [materialList, setMaterialList] = useState([]);
     const { showMessage } = useToast();
 
@@ -303,35 +307,24 @@ const Screen = ({ navigation }) => {
                             loading={loading}
                         >
                             <Form.Field>
-                                <Form.Require style={{width:titleWidth}}>
+                                <Form.Require style={{ width: titleWidth }}>
                                     <Form.Label>입고일</Form.Label>
                                 </Form.Require>
                                 <Form.Input value={moment(data.StoredDate).format('YYYY-MM-DD')} editable={false} />
                             </Form.Field>
 
                             <Form.Field>
-                                <Form.Require style={{width:titleWidth}}>
+                                <Form.Require style={{ width: titleWidth }}>
                                     <Form.Label>입고시간</Form.Label>
                                 </Form.Require>
                                 <Form.Input value={moment(data.StoredDate).format('HH:mm')} editable={false} />
                             </Form.Field>
 
                             <Form.Field>
-                                <Form.Require style={{width:titleWidth}}>
+                                <Form.Require style={{ width: titleWidth }}>
                                     <Form.Label>업무분야</Form.Label>
                                 </Form.Require>
-                                <Form.EntitySelect
-                                    entity="CmBusinessField"
-                                    defaultLabel="업무분야"
-                                    selectedValue={data.BusinessFieldId}
-                                    selectedText={Util.get(data, 'CmBusinessField.Name')}
-                                    editable={editable}
-                                    auth={auth}
-                                    useCheck={true}
-                                    onChange={(item) => {
-                                        setValue('BusinessFieldId', item.value, true);
-                                    }}
-                                />
+                                <Form.Input value={Util.get(data, 'CmBusinessField.Name')} editable={false} />
                             </Form.Field>
                             <Form.Regist
                                 editable={editable}
@@ -341,7 +334,7 @@ const Screen = ({ navigation }) => {
                             />
 
                             <Form.Field>
-                                <Form.Require style={{width:titleWidth}}>
+                                <Form.Require style={{ width: titleWidth }}>
                                     <Form.Label>구매발주서</Form.Label>
                                 </Form.Require>
                                 <Controller
@@ -368,6 +361,8 @@ const Screen = ({ navigation }) => {
                                                     console.log('item', item);
                                                     setValue('OrderTitle', item.Title);
                                                     setValue('PurchaseOrderId', item.PurchaseOrderId);
+                                                    setValue('BusinessFieldId', item.BusinessFieldId);
+                                                    Util.set(data, 'CmBusinessField.Name', item.BusinessFieldName);
                                                     item.MaterialPurchaseOrderMaterial.forEach((item) => {
                                                         item.MaterialName = item.Name;
                                                         item.MaterialStandard = item.Standard;
@@ -396,7 +391,7 @@ const Screen = ({ navigation }) => {
                             />
 
                             <Form.Field>
-                                <Form.Require style={{width:titleWidth}}>
+                                <Form.Require style={{ width: titleWidth }}>
                                     <Form.Label>창고명칭</Form.Label>
                                 </Form.Require>
                                 <Form.EntitySelect
@@ -426,7 +421,7 @@ const Screen = ({ navigation }) => {
                             />
 
                             <Form.Field>
-                                <Form.Title style={{width:titleWidth}}>
+                                <Form.Title style={{ width: titleWidth }}>
                                     <Form.Label>자재위치</Form.Label>
                                 </Form.Title>
                                 <Form.Input
@@ -439,7 +434,7 @@ const Screen = ({ navigation }) => {
                             <Form.Regist editable={editable} name="LocationInWarehouse" />
 
                             <Form.Field>
-                                <Form.Title style={{width:titleWidth}}>
+                                <Form.Title style={{ width: titleWidth }}>
                                     <Form.Label>비고</Form.Label>
                                 </Form.Title>
                                 <Form.Input
@@ -453,7 +448,7 @@ const Screen = ({ navigation }) => {
                             <Form.Regist editable={editable} name="Note" />
 
                             <Form.Field>
-                                <Form.Title style={{width:titleWidth}}>
+                                <Form.Title style={{ width: titleWidth }}>
                                     <Form.Label>{action == Form.CREATE ? '발주비고' : '구매사유'}</Form.Label>
                                 </Form.Title>
                                 <Text>{data.OrderReason}</Text>

+ 42 - 29
src/Screens/Root/QRScan/index.js

@@ -11,6 +11,7 @@ import Form from '~/Components/Form';
 import { Svg } from '~/Components/UIControls/Svg';
 import { Util } from '~/Utils/utils';
 import session from '~/Utils/session';
+import EmptyLayout from '~/Components/Layouts/EmptyLayout';
 
 const MenuBackground = Styled.View`
     position: absolute;
@@ -88,8 +89,8 @@ const Screen = (props) => {
     }, []);
 
     const handleBarCodeScanned = ({ type, data }) => {
-        if(!qrcode.scanned) {
-            setQRCode({ scanned: true, qrcode: data});
+        if (!qrcode.scanned) {
+            setQRCode({ scanned: true, qrcode: data });
         }
     };
 
@@ -99,28 +100,28 @@ const Screen = (props) => {
                 console.log('close qrscan...');
                 navigation.navigate('Dashboard');
             },
-        }
+        };
         actions[action]();
-    }
+    };
 
     let message = '';
-    if(hasPermission === null) {
+    if (hasPermission === null) {
         message = '카메라 접근권한을 허용해 주세요.';
     }
-    if(hasPermission === false) {
+    if (hasPermission === false) {
         message = '카메라 접근권한이 없습니다.';
     }
 
     return (
-        <PopupLayout header={null} style={{ }}>
-            <Form.Container style={{display:'none'}} onAction={actionHandler} />
+        <EmptyLayout>
+            <Form.Container style={{ display: 'none' }} onAction={actionHandler} />
             {hasPermission ? (
                 <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'flex-end' }}>
                     <BarCodeScanner onBarCodeScanned={handleBarCodeScanned} style={StyleSheet.absoluteFillObject} />
                 </View>
             ) : (
-                <View style={{ width:'100%', height:'100%', alignItems:'center', justifyContent:'center' }}>
-                    <Text style={[ListStyle.textMediumLarge, {fontSize:25, lineHeight:35}]}>{message}</Text>
+                <View style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center' }}>
+                    <Text style={[ListStyle.textMediumLarge, { fontSize: 25, lineHeight: 35 }]}>{message}</Text>
                 </View>
             )}
             {qrcode.scanned ? (
@@ -128,18 +129,28 @@ const Screen = (props) => {
                     <MenuBackground />
                     <MenuOuterContainer>
                         <MenuContainer>
-                            <MenuHeader><MenuTitle>QR:{qrcode.qrcode}</MenuTitle></MenuHeader>
+                            <MenuHeader>
+                                <MenuTitle>QR:{qrcode.qrcode}</MenuTitle>
+                            </MenuHeader>
                             <MenuContent>
                                 <ItemContainer>
-                                    <Item onPress={()=>{
-                                        Util.navigate(navigation, session.getMenu('/Facility/Facility'), null, { qrcode: qrcode.qrcode });
-                                    }}>
+                                    <Item
+                                        onPress={() => {
+                                            Util.navigate(navigation, session.getMenu('/Facility/Facility'), null, {
+                                                qrcode: qrcode.qrcode,
+                                            });
+                                        }}
+                                    >
                                         <Svg path="/qrscan/facility" width={25} height={25} />
                                         <ItemText>설비조회</ItemText>
                                     </Item>
-                                    <Item onPress={()=>{
-                                        Util.navigate(navigation, session.getMenu('/Energy/ManualMeter'), null, { qrcode: qrcode.qrcode });
-                                    }}>
+                                    <Item
+                                        onPress={() => {
+                                            Util.navigate(navigation, session.getMenu('/Energy/ManualMeter'), null, {
+                                                qrcode: qrcode.qrcode,
+                                            });
+                                        }}
+                                    >
                                         <Svg path="/qrscan/manual_meter" width={25} height={25} />
                                         <ItemText>수검침 등록</ItemText>
                                     </Item>
@@ -148,20 +159,22 @@ const Screen = (props) => {
                         </MenuContainer>
                     </MenuOuterContainer>
                 </Fragment>
-            ):null}
-        </PopupLayout>
+            ) : null}
+        </EmptyLayout>
     );
-}
+};
 
 // header
-Screen.navigationOptions = ({navigation}) => { 
-    return { 
-        header: () => <Header 
-            navigation={navigation} 
-            title="QR코드" 
-            buttons={<Form.ActionButton navigation={navigation} type="primary" action="close" title="닫기" />}
-        /> 
-    }
+Screen.navigationOptions = ({ navigation }) => {
+    return {
+        header: () => (
+            <Header
+                navigation={navigation}
+                title="QR코드"
+                buttons={<Form.ActionButton navigation={navigation} type="primary" action="close" title="닫기" />}
+            />
+        ),
+    };
 };
 
-export default Screen;
+export default Screen;

+ 5 - 0
src/Screens/Root/Report/DailyReport/Form.js

@@ -106,6 +106,11 @@ const Screen = ({navigation}) => {
                 result.MonthUsage += Util.get(item, "MonitoringPoint.MonthUsage");
             }
 
+            result.Today = Math.round(result.Today * 100.0) / 100.0;
+            result.DayBefore = Math.round(result.DayBefore * 100.0) / 100.0;
+            result.DailyUsage = Math.round(result.DailyUsage * 100.0) / 100.0;
+            result.MonthUsage = Math.round(result.MonthUsage * 100.0) / 100.0;
+
             return result;
         }
 

+ 548 - 230
src/Screens/Root/Report/DailyReport/SubPages/BasicInfoForm.js

@@ -12,6 +12,8 @@ import { usePrompt } from '~/Components/UIControls/Message';
 import Weather from '~/Screens/Dashboard/Weather';
 import { isTrue } from '~/Components/UIControls/Common';
 import { UploadFileType } from '~/Components/UIControls/UploadFile';
+import Button from '~/Components/UIControls/Button';
+import { usePopup } from '~/Components/UIControls/Popup';
 
 const Human = Styled.View`
     flex-direction: row;
@@ -35,19 +37,19 @@ const HumanName = Styled.Text`
     letter-spacing: -1.6;
     color: white;
 `;
-const HumanRemove = ({onPress=()=>{}}) => {
+const HumanRemove = ({ onPress = () => {} }) => {
     return (
-        <IconButton iconFamily="AntDesign" iconName="minuscircle" color="white" size={20} onPress={onPress} style={{marginLeft:10}} />
-    )
-}
+        <IconButton iconFamily="AntDesign" iconName="minuscircle" color="white" size={20} onPress={onPress} style={{ marginLeft: 10 }} />
+    );
+};
+
+const HumanManager = ({ editable, initialHumans, setValue, humansDataPath }) => {
+    const [humans, setHumans] = useState(Array.isArray(initialHumans) ? initialHumans : []);
 
-const HumanManager = ({editable, initialHumans, setValue, humansDataPath}) => {
-    const [ humans, setHumans ] = useState(Array.isArray(initialHumans) ? initialHumans : []);
-    
     const { prompt } = usePrompt();
 
     useEffect(() => {
-        if(Array.isArray(initialHumans)) {
+        if (Array.isArray(initialHumans)) {
             setValue(humansDataPath, [...initialHumans]);
             setHumans([...initialHumans]);
         } else {
@@ -57,110 +59,171 @@ const HumanManager = ({editable, initialHumans, setValue, humansDataPath}) => {
     }, [editable]);
 
     const addHuman = () => {
-        prompt({title:'인원명', message:'추가할 인원의 이름을 입력하세요.', defaultValue:'', confirm:(text) => {
-            let newHumans = [...humans];
-            newHumans.push(text);
-            setValue(humansDataPath, newHumans, true);
-            setHumans(newHumans);
-        }});
-    }
+        prompt({
+            title: '인원명',
+            message: '추가할 인원의 이름을 입력하세요.',
+            defaultValue: '',
+            confirm: (text) => {
+                let newHumans = [...humans];
+                newHumans.push(text);
+                setValue(humansDataPath, newHumans, true);
+                setHumans(newHumans);
+            },
+        });
+    };
 
     const removeHuman = (index) => {
         let newHumans = [];
-        for(let i=0; i<humans.length; i++) {
-            if(index == i) continue;
+        for (let i = 0; i < humans.length; i++) {
+            if (index == i) continue;
             newHumans.push(humans[i]);
         }
         setValue(humansDataPath, newHumans, true);
         setHumans(newHumans);
-    }
+    };
 
     return (
         <Fragment>
             <Form.FieldSetHead>
-                <Form.Legend><Form.LegendLabel>인원목록</Form.LegendLabel></Form.Legend>
+                <Form.Legend>
+                    <Form.LegendLabel>인원목록</Form.LegendLabel>
+                </Form.Legend>
                 <Form.ButtonGroup>
-                    {isTrue(editable) && <Form.HeadButton onPress={() => { addHuman() }}><Form.LegendLabel>추가</Form.LegendLabel></Form.HeadButton>}
+                    {isTrue(editable) && (
+                        <Form.HeadButton
+                            onPress={() => {
+                                addHuman();
+                            }}
+                        >
+                            <Form.LegendLabel>추가</Form.LegendLabel>
+                        </Form.HeadButton>
+                    )}
                 </Form.ButtonGroup>
             </Form.FieldSetHead>
-            <Form.FieldSet style={{flexDirection:'row', flexWrap:'wrap', alignItems:'flex-start'}}>
-                {humans && Array.isArray(humans) && humans.length > 0 ? humans.map((name, index) => {
-                    return (
-                        <Fragment key={`human-${index}`}>
-                            <Human style={!isTrue(editable) && {backgroundColor:'#9aa3ac'}}>
-                                <HumanName>{name}</HumanName>
-                                {isTrue(editable) && <HumanRemove onPress={() => { removeHuman(index) }} />}
-                            </Human>
-                        </Fragment>
-                    )
-                }) : (
-                    <View style={{flex:1, height:100, justifyContent:'center', alignItems:'center'}}>
-                        <Form.Label style={{ 
-                            textAlign:'center', fontFamily:Theme.Fonts.Regular, 
-                            letterSpacing:-1.6, fontSize:18, lineHeight:30 
-                        }}>인원을 추가해 주세요.</Form.Label>
+            <Form.FieldSet style={{ flexDirection: 'row', flexWrap: 'wrap', alignItems: 'flex-start' }}>
+                {humans && Array.isArray(humans) && humans.length > 0 ? (
+                    humans.map((name, index) => {
+                        return (
+                            <Fragment key={`human-${index}`}>
+                                <Human style={!isTrue(editable) && { backgroundColor: '#9aa3ac' }}>
+                                    <HumanName>{name}</HumanName>
+                                    {isTrue(editable) && (
+                                        <HumanRemove
+                                            onPress={() => {
+                                                removeHuman(index);
+                                            }}
+                                        />
+                                    )}
+                                </Human>
+                            </Fragment>
+                        );
+                    })
+                ) : (
+                    <View style={{ flex: 1, height: 100, justifyContent: 'center', alignItems: 'center' }}>
+                        <Form.Label
+                            style={{
+                                textAlign: 'center',
+                                fontFamily: Theme.Fonts.Regular,
+                                letterSpacing: -1.6,
+                                fontSize: 18,
+                                lineHeight: 30,
+                            }}
+                        >
+                            인원을 추가해 주세요.
+                        </Form.Label>
                     </View>
                 )}
             </Form.FieldSet>
             <Form.Regist name={humansDataPath} />
         </Fragment>
-    )
-}
+    );
+};
 
-export default Screen = ({navigation, register, unregister, data, setData, setValue, errors}) => {
+export default Screen = ({ navigation, register, unregister, data, setData, setValue, errors }) => {
     const action = navigation.getParam('action', Form.VIEW);
     const editable = navigation.getParam('editable', action == Form.VIEW ? false : true);
-    const setEditable = (value) => { navigation.setParams({editable: value}) };
-    const refreshList = navigation.getParam('refreshList', ()=>{});
+    const setEditable = (value) => {
+        navigation.setParams({ editable: value });
+    };
+    const refreshList = navigation.getParam('refreshList', () => {});
     const siteId = navigation.getParam('siteId', 0);
     const addDate = navigation.getParam('addDate', new Date());
-    const setAddDate = (value) => { navigation.setParams({addDate: value}) };
+    const setAddDate = (value) => {
+        navigation.setParams({ addDate: value });
+    };
     const businessFieldId = navigation.getParam('businessFieldId', 0);
     const isApproved = navigation.getParam('isApproved', false);
 
+    const { openPopup } = usePopup();
+
     return (
         <EmptyLayout>
-            <Form.Container id="daily-report-basic-info-form" style={{paddingLeft:0, paddingTop:0, paddingRight:0, paddingBottom:0}}>
+            <Form.Container id="daily-report-basic-info-form" style={{ paddingLeft: 0, paddingTop: 0, paddingRight: 0, paddingBottom: 0 }}>
                 <Form.FieldSetHead>
-                    <Form.Legend><Form.LegendLabel>기본정보</Form.LegendLabel></Form.Legend>
+                    <Form.Legend>
+                        <Form.LegendLabel>기본정보</Form.LegendLabel>
+                    </Form.Legend>
                 </Form.FieldSetHead>
                 <Form.FieldSet>
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>제목</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={data.Name} onChangeText={(text) => {
-                            setValue('Name', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>제목</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={data.Name}
+                            onChangeText={(text) => {
+                                setValue('Name', text, true);
+                            }}
+                        />
                     </Form.Field>
-                    <Form.Regist editable={editable} name="Name" rule={{required:'제목을 입력하세요.'}} error={errors.SitemapId} />
+                    <Form.Regist editable={editable} name="Name" rule={{ required: '제목을 입력하세요.' }} error={errors.SitemapId} />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>특이사항</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={data.Contents} onChangeText={(text) => {
-                            setValue('Contents', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>특이사항</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={data.Contents}
+                            onChangeText={(text) => {
+                                setValue('Contents', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="Contents" />
 
                     <Form.Field>
-                        <Form.TitleTop style={{justifyContent:'flex-end'}}><Form.Label>첨부파일</Form.Label></Form.TitleTop>
-                        <Form.UploadFile type={UploadFileType.Image} editable={editable} defaultFile={data.CmFile}
+                        <Form.TitleTop style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>첨부파일</Form.Label>
+                        </Form.TitleTop>
+                        <Form.UploadFile
+                            type={UploadFileType.Image}
+                            editable={editable}
+                            defaultFile={data.CmFile}
                             onUpload={(isUpload, result) => {
                                 Form.uploadFile('CmFile', isUpload, result);
-                            }} onDelete={() => {
+                            }}
+                            onDelete={() => {
                                 Form.deleteFile('CmFile');
-                            }} />
+                            }}
+                        />
                     </Form.Field>
-                    <Form.RegistFile editable={editable} name="CmFile" value={Util.get(data, "CmFile")} />
+                    <Form.RegistFile editable={editable} name="CmFile" value={Util.get(data, 'CmFile')} />
                 </Form.FieldSet>
 
                 {isApproved && (
                     <Fragment>
                         <Form.FieldSetHead>
-                            <Form.Legend><Form.LegendLabel>결재정보</Form.LegendLabel></Form.Legend>
+                            <Form.Legend>
+                                <Form.LegendLabel>결재정보</Form.LegendLabel>
+                            </Form.Legend>
                         </Form.FieldSetHead>
                         <Form.FieldSet>
                             <Form.Field>
-                                <Form.Title><Form.Label>결재자</Form.Label></Form.Title>
+                                <Form.Title>
+                                    <Form.Label>결재자</Form.Label>
+                                </Form.Title>
                                 <Form.Input editable={editable} defaultValue={data.ApproverUserName} />
                             </Form.Field>
                             {/*
@@ -186,237 +249,492 @@ export default Screen = ({navigation, register, unregister, data, setData, setVa
                 )}
 
                 <Form.FieldSetHead>
-                    <Form.Legend><Form.LegendLabel>날씨정보</Form.LegendLabel></Form.Legend>
+                    <Form.Legend>
+                        <Form.LegendLabel>날씨정보</Form.LegendLabel>
+                    </Form.Legend>
                 </Form.FieldSetHead>
-                <Weather doNotFetch={true} weatherinfo={Util.get(data, "DataObject.Weather")} style={{marginTop:10}} />
+                <Weather doNotFetch={true} weatherinfo={Util.get(data, 'DataObject.Weather')} style={{ marginTop: 10 }} />
 
                 <Form.FieldSetHead>
-                    <Form.Legend><Form.LegendLabel>인원현황</Form.LegendLabel></Form.Legend>
+                    <Form.Legend>
+                        <Form.LegendLabel>인원현황</Form.LegendLabel>
+                    </Form.Legend>
                 </Form.FieldSetHead>
                 <Form.FieldSet>
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>총원</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceTotal")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceTotal', text, true)
-                        }} />
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>결원</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceVacancy")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceVacancy', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>총원</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceTotal')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceTotal', text, true);
+                            }}
+                        />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>결원</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceVacancy')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceVacancy', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceTotal" />
                     <Form.Regist editable={editable} name="DataObject.HumanResourceVacancy" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>비번</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceOff")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceOff', text, true)
-                        }} />
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>휴가</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceVacation")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceVacation', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>비번</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceOff')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceOff', text, true);
+                            }}
+                        />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>휴가</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceVacation')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceVacation', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceOff" />
                     <Form.Regist editable={editable} name="DataObject.HumanResourceVacation" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>휴무</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceClosed")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceClosed', text, true)
-                        }} />
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>교육</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceTrain")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceTrain', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>휴무</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceClosed')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceClosed', text, true);
+                            }}
+                        />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>교육</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceTrain')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceTrain', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceClosed" />
                     <Form.Regist editable={editable} name="DataObject.HumanResourceTrain" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>출장</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceOut")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceOut', text, true)
-                        }} />
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>당직</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceEtc")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceEtc', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>출장</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceOut')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceOut', text, true);
+                            }}
+                        />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>당직</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceEtc')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceEtc', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceOut" />
                     <Form.Regist editable={editable} name="DataObject.HumanResourceEtc" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>현원</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceCurrent")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceCurrent', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>현원</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceCurrent')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceCurrent', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceCurrent" />
                 </Form.FieldSet>
 
                 <Form.FieldSetHead>
-                    <Form.Legend><Form.LegendLabel>인원내역</Form.LegendLabel></Form.Legend>
+                    <Form.Legend>
+                        <Form.LegendLabel>인원내역</Form.LegendLabel>
+                    </Form.Legend>
                 </Form.FieldSetHead>
                 <Form.FieldSet>
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>비번</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceOffName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceOffName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>비번</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceOffName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceOffName', text, true);
+                            }}
+                        />
+                        {/*
+                        <Button
+                            style={{
+                                width: 60,
+                                paddingLeft: 3,
+                                paddingRight: 0,
+                                paddingTop: 0,
+                                paddingBottom: 0,
+                            }}
+                            buttonStyle={{ height: 40 }}
+                            textStyle={{ fontSize: 14 }}
+                            onPress={() => {
+                                openPopup('/Popup/DragDropSample/Index', {}, (result) => {
+                                    setValue('DataObject.HumanResourceOffName', result, true);
+                                    setData({ ...data, DataObject: { ...data.DataObject, HumanResourceOffName: result } });
+                                });
+                            }}
+                        >
+                            선택
+                        </Button>
+                        */}
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceOffName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>휴가</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceVacationName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceVacationName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>휴가</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceVacationName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceVacationName', text, true);
+                            }}
+                        />
+                        {/*
+                        <Button
+                            style={{
+                                width: 60,
+                                paddingLeft: 3,
+                                paddingRight: 0,
+                                paddingTop: 0,
+                                paddingBottom: 0,
+                            }}
+                            buttonStyle={{ height: 40 }}
+                            textStyle={{ fontSize: 14 }}
+                            onPress={() => {
+                                openPopup('/Popup/DragDropSample/Index', {}, (result) => {
+                                    setValue('DataObject.HumanResourceVacationName', result, true);
+                                    setData({ ...data, DataObject: { ...data.DataObject, HumanResourceVacationName: result } });
+                                });
+                            }}
+                        >
+                            선택
+                        </Button>
+                        */}
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceVacationName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>휴무</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceClosedName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceClosedName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>휴무</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceClosedName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceClosedName', text, true);
+                            }}
+                        />
+                        {/*
+                        <Button
+                            style={{
+                                width: 60,
+                                paddingLeft: 3,
+                                paddingRight: 0,
+                                paddingTop: 0,
+                                paddingBottom: 0,
+                            }}
+                            buttonStyle={{ height: 40 }}
+                            textStyle={{ fontSize: 14 }}
+                            onPress={() => {
+                                openPopup('/Popup/DragDropSample/Index', {}, (result) => {
+                                    setValue('DataObject.HumanResourceClosedName', result, true);
+                                    setData({ ...data, DataObject: { ...data.DataObject, HumanResourceClosedName: result } });
+                                });
+                            }}
+                        >
+                            선택
+                        </Button>
+                        */}
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceClosedName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>교육</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceTrainName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceTrainName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>교육</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceTrainName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceTrainName', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceTrainName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>출장</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceOutName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceOutName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>출장</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceOutName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceOutName', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceOutName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>당직</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceEtcName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceEtcName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>당직</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceEtcName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceEtcName', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceEtcName" />
 
                     <Form.Field>
-                        <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>현원</Form.Label></Form.Title>
-                        <Form.Input editable={editable} defaultValue={Util.get(data, "DataObject.HumanResourceCurrentName")} onChangeText={(text) => {
-                            setValue('DataObject.HumanResourceCurrentName', text, true)
-                        }} />
+                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                            <Form.Label>현원</Form.Label>
+                        </Form.Title>
+                        <Form.Input
+                            editable={editable}
+                            defaultValue={Util.get(data, 'DataObject.HumanResourceCurrentName')}
+                            onChangeText={(text) => {
+                                setValue('DataObject.HumanResourceCurrentName', text, true);
+                            }}
+                        />
                     </Form.Field>
                     <Form.Regist editable={editable} name="DataObject.HumanResourceCurrentName" />
                 </Form.FieldSet>
 
-                {Util.get(data, "DataObject.Energies") && Util.get(data, "DataObject.Energies").map((energy, energyIndex) => {
-                    return (
-                        <Fragment key={`summary-${energyIndex}`}>
-                            <Form.SeparateLine style={{display:'none'}}>
-                                <Form.SeparateLabel>{Util.get(energy, `FacilityTypeName`)}</Form.SeparateLabel>
-                            </Form.SeparateLine>
-                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].FacilityTypeName`} />
-
-                            {Util.get(energy, "List") && Util.get(energy, "List").map((item, itemIndex) => {
-                                return (
-                                    <Fragment key={`item-${energyIndex}-${itemIndex}`}>
-                                        <Form.FieldSetHead style={{display:'none'}}>
-                                            <Form.Legend><Form.LegendLabel>{Util.get(item, "Name")}</Form.LegendLabel></Form.Legend>
-                                        </Form.FieldSetHead>
-                                        <Form.FieldSet style={{display:'none'}}>
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].FacilityCode`} />
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].PropertyId`} />
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].Name`} />
-
-                                            <Form.Field>
-                                                <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>금일</Form.Label></Form.Title>
-                                                <Form.Input editable={editable} defaultValue={Util.get(item, "Today")} onChangeText={(text) => {
-                                                    setValue(`DataObject.Energies[${energyIndex}].List[${itemIndex}].Today`, text, true);
-                                                }} />
-                                            </Form.Field>
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].Today`} />
-
-                                            <Form.Field>
-                                                <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>전일</Form.Label></Form.Title>
-                                                <Form.Input editable={editable} defaultValue={Util.get(item, "DayBefore")} onChangeText={(text) => {
-                                                    setValue(`DataObject.Energies[${energyIndex}].List[${itemIndex}].DayBefore`, text, true);
-                                                }} />
-                                            </Form.Field>
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].DayBefore`} />
-
-                                            <Form.Field>
-                                                <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>금일사용량</Form.Label></Form.Title>
-                                                <Form.Input editable={editable} defaultValue={Util.get(item, "DailyUsage")} onChangeText={(text) => {
-                                                    setValue(`DataObject.Energies[${energyIndex}].List[${itemIndex}].DailyUsage`, text, true);
-                                                }} />
-                                            </Form.Field>
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].DailyUsage`} />
-
-                                            <Form.Field>
-                                                <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>당월사용량</Form.Label></Form.Title>
-                                                <Form.Input editable={editable} defaultValue={Util.get(item, "MonthUsage")} onChangeText={(text) => {
-                                                    setValue(`DataObject.Energies[${energyIndex}].List[${itemIndex}].MonthUsage`, text, true);
-                                                }} />
-                                            </Form.Field>
-                                            <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].MonthUsage`} />
-                                        </Form.FieldSet>
-                                    </Fragment>
-                                )
-                            })}
-
-                            <Form.FieldSetHead style={{borderColor:'chocolate'}}>
-                                <Form.Legend style={{backgroundColor:'chocolate'}}><Form.LegendLabel>{Util.get(energy, "Total.Name")}</Form.LegendLabel></Form.Legend>
-                            </Form.FieldSetHead>
-                            <Form.FieldSet>
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].FacilityTypeId`} />
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.Name`} />
-
-                                <Form.Field>
-                                    <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>금일</Form.Label></Form.Title>
-                                    <Form.Input editable={editable} defaultValue={Util.get(energy, "Total.Today")} onChangeText={(text) => {
-                                        setValue(`DataObject.Energies[${energyIndex}].Total.Today`, text, true);
-                                    }} />
-                                </Form.Field>
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.Today`} />
-
-                                <Form.Field>
-                                    <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>전일</Form.Label></Form.Title>
-                                    <Form.Input editable={editable} defaultValue={Util.get(energy, "Total.DayBefore")} onChangeText={(text) => {
-                                        setValue(`DataObject.Energies[${energyIndex}].Total.DayBefore`, text, true);
-                                    }} />
-                                </Form.Field>
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.DayBefore`} />
-
-                                <Form.Field>
-                                    <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>금일사용량</Form.Label></Form.Title>
-                                    <Form.Input editable={editable} defaultValue={Util.get(energy, "Total.DailyUsage")} onChangeText={(text) => {
-                                        setValue(`DataObject.Energies[${energyIndex}].Total.DailyUsage`, text, true);
-                                    }} />
-                                </Form.Field>
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.DailyUsage`} />
-                                
-                                <Form.Field>
-                                    <Form.Title style={{justifyContent:'flex-end'}}><Form.Label>당월사용량</Form.Label></Form.Title>
-                                    <Form.Input editable={editable} defaultValue={Util.get(energy, "Total.MonthUsage")} onChangeText={(text) => {
-                                        setValue(`DataObject.Energies[${energyIndex}].Total.MonthUsage`, text, true);
-                                    }} />
-                                </Form.Field>
-                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.MonthUsage`} />
-                            </Form.FieldSet>
-                        </Fragment>
-                    )
-                })}
-
-                <Form.Field style={{height:100}} />
-
+                {Util.get(data, 'DataObject.Energies') &&
+                    Util.get(data, 'DataObject.Energies').map((energy, energyIndex) => {
+                        return (
+                            <Fragment key={`summary-${energyIndex}`}>
+                                <Form.SeparateLine style={{ display: 'none' }}>
+                                    <Form.SeparateLabel>{Util.get(energy, `FacilityTypeName`)}</Form.SeparateLabel>
+                                </Form.SeparateLine>
+                                <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].FacilityTypeName`} />
+
+                                {Util.get(energy, 'List') &&
+                                    Util.get(energy, 'List').map((item, itemIndex) => {
+                                        return (
+                                            <Fragment key={`item-${energyIndex}-${itemIndex}`}>
+                                                <Form.FieldSetHead style={{ display: 'none' }}>
+                                                    <Form.Legend>
+                                                        <Form.LegendLabel>{Util.get(item, 'Name')}</Form.LegendLabel>
+                                                    </Form.Legend>
+                                                </Form.FieldSetHead>
+                                                <Form.FieldSet style={{ display: 'none' }}>
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].FacilityCode`}
+                                                    />
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].PropertyId`}
+                                                    />
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].Name`}
+                                                    />
+
+                                                    <Form.Field>
+                                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                                            <Form.Label>금일</Form.Label>
+                                                        </Form.Title>
+                                                        <Form.Input
+                                                            editable={editable}
+                                                            defaultValue={Util.get(item, 'Today')}
+                                                            onChangeText={(text) => {
+                                                                setValue(
+                                                                    `DataObject.Energies[${energyIndex}].List[${itemIndex}].Today`,
+                                                                    text,
+                                                                    true,
+                                                                );
+                                                            }}
+                                                        />
+                                                    </Form.Field>
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].Today`}
+                                                    />
+
+                                                    <Form.Field>
+                                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                                            <Form.Label>전일</Form.Label>
+                                                        </Form.Title>
+                                                        <Form.Input
+                                                            editable={editable}
+                                                            defaultValue={Util.get(item, 'DayBefore')}
+                                                            onChangeText={(text) => {
+                                                                setValue(
+                                                                    `DataObject.Energies[${energyIndex}].List[${itemIndex}].DayBefore`,
+                                                                    text,
+                                                                    true,
+                                                                );
+                                                            }}
+                                                        />
+                                                    </Form.Field>
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].DayBefore`}
+                                                    />
+
+                                                    <Form.Field>
+                                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                                            <Form.Label>금일사용량</Form.Label>
+                                                        </Form.Title>
+                                                        <Form.Input
+                                                            editable={editable}
+                                                            defaultValue={Util.get(item, 'DailyUsage')}
+                                                            onChangeText={(text) => {
+                                                                setValue(
+                                                                    `DataObject.Energies[${energyIndex}].List[${itemIndex}].DailyUsage`,
+                                                                    text,
+                                                                    true,
+                                                                );
+                                                            }}
+                                                        />
+                                                    </Form.Field>
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].DailyUsage`}
+                                                    />
+
+                                                    <Form.Field>
+                                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                                            <Form.Label>당월사용량</Form.Label>
+                                                        </Form.Title>
+                                                        <Form.Input
+                                                            editable={editable}
+                                                            defaultValue={Util.get(item, 'MonthUsage')}
+                                                            onChangeText={(text) => {
+                                                                setValue(
+                                                                    `DataObject.Energies[${energyIndex}].List[${itemIndex}].MonthUsage`,
+                                                                    text,
+                                                                    true,
+                                                                );
+                                                            }}
+                                                        />
+                                                    </Form.Field>
+                                                    <Form.Regist
+                                                        editable={editable}
+                                                        name={`DataObject.Energies[${energyIndex}].List[${itemIndex}].MonthUsage`}
+                                                    />
+                                                </Form.FieldSet>
+                                            </Fragment>
+                                        );
+                                    })}
+
+                                <Form.FieldSetHead style={{ borderColor: 'chocolate' }}>
+                                    <Form.Legend style={{ backgroundColor: 'chocolate' }}>
+                                        <Form.LegendLabel>{Util.get(energy, 'Total.Name')}</Form.LegendLabel>
+                                    </Form.Legend>
+                                </Form.FieldSetHead>
+                                <Form.FieldSet>
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].FacilityTypeId`} />
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.Name`} />
+
+                                    <Form.Field>
+                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                            <Form.Label>금일</Form.Label>
+                                        </Form.Title>
+                                        <Form.Input
+                                            editable={editable}
+                                            defaultValue={Util.get(energy, 'Total.Today')}
+                                            onChangeText={(text) => {
+                                                setValue(`DataObject.Energies[${energyIndex}].Total.Today`, text, true);
+                                            }}
+                                        />
+                                    </Form.Field>
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.Today`} />
+
+                                    <Form.Field>
+                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                            <Form.Label>전일</Form.Label>
+                                        </Form.Title>
+                                        <Form.Input
+                                            editable={editable}
+                                            defaultValue={Util.get(energy, 'Total.DayBefore')}
+                                            onChangeText={(text) => {
+                                                setValue(`DataObject.Energies[${energyIndex}].Total.DayBefore`, text, true);
+                                            }}
+                                        />
+                                    </Form.Field>
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.DayBefore`} />
+
+                                    <Form.Field>
+                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                            <Form.Label>금일사용량</Form.Label>
+                                        </Form.Title>
+                                        <Form.Input
+                                            editable={editable}
+                                            defaultValue={Util.get(energy, 'Total.DailyUsage')}
+                                            onChangeText={(text) => {
+                                                setValue(`DataObject.Energies[${energyIndex}].Total.DailyUsage`, text, true);
+                                            }}
+                                        />
+                                    </Form.Field>
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.DailyUsage`} />
+
+                                    <Form.Field>
+                                        <Form.Title style={{ justifyContent: 'flex-end' }}>
+                                            <Form.Label>당월사용량</Form.Label>
+                                        </Form.Title>
+                                        <Form.Input
+                                            editable={editable}
+                                            defaultValue={Util.get(energy, 'Total.MonthUsage')}
+                                            onChangeText={(text) => {
+                                                setValue(`DataObject.Energies[${energyIndex}].Total.MonthUsage`, text, true);
+                                            }}
+                                        />
+                                    </Form.Field>
+                                    <Form.Regist editable={editable} name={`DataObject.Energies[${energyIndex}].Total.MonthUsage`} />
+                                </Form.FieldSet>
+                            </Fragment>
+                        );
+                    })}
+
+                <Form.Field style={{ height: 100 }} />
             </Form.Container>
         </EmptyLayout>
-    )
-};
+    );
+};

+ 18 - 7
src/Screens/Root/Report/ReportHistory/Form.js

@@ -54,7 +54,6 @@ const Screen = ({ navigation }) => {
             try {
                 const result = await fetchGet(`api/app/ReportHistory/Get?siteId=${siteId}&seq=${seq}`);
                 setData(result);
-                console.log(result);
                 setEditable(editable);
             } catch (error) {
                 showMessage(error.message);
@@ -107,7 +106,13 @@ const Screen = ({ navigation }) => {
                                 source={{
                                     html: `<!DOCTYPE html>
                                 <html>
-                                <head></head>
+                                <head>
+                                <style type='text/css'>
+                                .stamp {
+                                    max-height: 50px;
+                                }
+                                </style>
+                                </head>
                                 <body>
                                 <div id='ubitems-fixed-content' style='display:inline-block; position:relative;'>
                                 ${`
@@ -122,14 +127,20 @@ const Screen = ({ navigation }) => {
                                         <td style="height: 20px; text-align: center;">소장</td>
                                     </tr>
                                     <tr>
-                                        <td height="50" style="min-width: 50px; text-align: center;">
-                                        ${data.Confirm1??''}
+                                        <td height="50" style="min-width: 80px; text-align: center;">
+                                        ${!!data.ApproverUserStamp1 
+                                            ? ('<img src="' + Util.get(data, 'ApproverUserStamp1.Url') + '" class="stamp" />') 
+                                            : (data.Confirm1??'')}
+                                        </td>
+                                        <td style="min-width: 80px; text-align: center;">
+                                        ${!!data.ApproverUserStamp2 
+                                            ? ('<img src="' + Util.get(data, 'ApproverUserStamp2.Url') + '" class="stamp" />') 
+                                            : (data.Confirm2??'')}
                                         </td>
-                                        <td style="min-width: 50px; text-align: center;">${data.Confirm2??''}</td>
                                     </tr>
                                     <tr>
-                                        <td style="height: 20px"></td>
-                                        <td style="height: 20px"></td>
+                                        <td style="height: 20px; text-align:center; font-size:11px">${data.ApproveDate1??''}</td>
+                                        <td style="height: 20px; text-align:center; font-size:11px">${data.ApproveDate2??''}</td>
                                     </tr>
                                     </table>
                                 </div>

+ 160 - 108
src/Utils/utils.js

@@ -1,10 +1,10 @@
-import { Dimensions, Linking } from "react-native";
-import { Svgs } from "~/Generated/Svgs";
-import { NavigationActions } from "react-navigation";
-import session from "./session";
+import { Dimensions, Linking } from 'react-native';
+import { Svgs } from '~/Generated/Svgs';
+import { NavigationActions } from 'react-navigation';
+import session from './session';
 import _ from 'lodash';
 import moment from 'moment';
-import { Config } from "~/Configuration";
+import { Config } from '~/Configuration';
 
 export const Util = {
     getStatusBarHeight: () => {
@@ -19,46 +19,62 @@ export const Util = {
     getScreenHeight: () => {
         return Util.getScreenSize().height;
     },
-    getBottomTabBarHeight: (tabCount=5) => {
+    getBottomTabBarHeight: (tabCount = 5) => {
         return Math.round(Util.getScreenWidth() / tabCount);
     },
-    getContentHeight: (headerHeight=50,tabCount=5) => {
+    getContentHeight: (headerHeight = 50, tabCount = 5) => {
         console.log(Util.getScreenHeight(), Util.getStatusBarHeight(), headerHeight, Util.getBottomTabBarHeight(tabCount));
         return Util.getScreenHeight() - Util.getStatusBarHeight() - headerHeight - Util.getBottomTabBarHeight(tabCount);
     },
-    
+
     toDate: (date) => {
-        if(typeof date === 'string') {
-            if(date.split('T').length == 2 && date.indexOf('Z') == -1) {
+        if (typeof date === 'string') {
+            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                 const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                 const matches = regexp.exec(date);
-                date = new Date(matches[1], parseInt(matches[2]) - 1, matches[3], matches[4], matches[5], matches[6], (matches[7] ? matches[7] : 0));
+                date = new Date(
+                    matches[1],
+                    parseInt(matches[2]) - 1,
+                    matches[3],
+                    matches[4],
+                    matches[5],
+                    matches[6],
+                    matches[7] ? matches[7] : 0,
+                );
             } else {
                 date = new Date(date);
             }
         }
-        if(date instanceof Date) return date;
-        if(!date) return new Date();
+        if (date instanceof Date) return date;
+        if (!date) return new Date();
         return new Date(date);
     },
 
-    formatDate: (date = new Date(), format='yyyy-MM-dd hh:mm:ss.zzz', nullValue='') => {
-        if(!date) return nullValue;
-        if(typeof date === 'string') {
-            if(date.split('T').length == 2 && date.indexOf('Z') == -1) {
+    formatDate: (date = new Date(), format = 'yyyy-MM-dd hh:mm:ss.zzz', nullValue = '') => {
+        if (!date) return nullValue;
+        if (typeof date === 'string') {
+            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                 const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                 const matches = regexp.exec(date);
-                date = new Date(matches[1], parseInt(matches[2]) - 1, matches[3], matches[4], matches[5], matches[6], (matches[7] ? matches[7] : 0));
+                date = new Date(
+                    matches[1],
+                    parseInt(matches[2]) - 1,
+                    matches[3],
+                    matches[4],
+                    matches[5],
+                    matches[6],
+                    matches[7] ? matches[7] : 0,
+                );
             } else {
                 date = new Date(date);
             }
         }
-        if(!date instanceof Date) date = new Date(date);
-        if(!date instanceof Date) return nullValue;
-        if(typeof date.getFullYear === 'undefined') return nullValue;
+        if (!date instanceof Date) date = new Date(date);
+        if (!date instanceof Date) return nullValue;
+        if (typeof date.getFullYear === 'undefined') return nullValue;
 
-        const weeks = ['일','월','화','수','목','금','토'];
-        const weeksLong = ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'];
+        const weeks = ['일', '월', '화', '수', '목', '금', '토'];
+        const weeksLong = ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'];
         let result = format;
         result = result.replace('yyyy', date.getFullYear());
         result = result.replace('MM', (date.getMonth() + 1 + '').padStart(2, '0'));
@@ -72,59 +88,83 @@ export const Util = {
         return result;
     },
 
-    toMonthString: (date = new Date(), nullValue='', seperate='-') => {
+    toMonthString: (date = new Date(), nullValue = '', seperate = '-') => {
         const mv = moment(date);
-        if(mv.isValid()) {
+        if (mv.isValid()) {
             return mv.format('YYYY') + seperate + mv.format('MM');
         } else {
             return '';
         }
     },
-    
-    toDateString: (date = new Date(), nullValue='', seperate='-') => {
-        if(!date) return nullValue;
-        if(typeof date === 'string') {
-            if(date.split('T').length == 2 && date.indexOf('Z') == -1) {
+
+    toDateString: (date = new Date(), nullValue = '', seperate = '-') => {
+        if (!date) return nullValue;
+        if (typeof date === 'string') {
+            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                 const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                 const matches = regexp.exec(date);
-                date = new Date(matches[1], parseInt(matches[2]) - 1, matches[3], matches[4], matches[5], matches[6], (matches[7] ? matches[7] : 0));
+                date = new Date(
+                    matches[1],
+                    parseInt(matches[2]) - 1,
+                    matches[3],
+                    matches[4],
+                    matches[5],
+                    matches[6],
+                    matches[7] ? matches[7] : 0,
+                );
             } else {
                 date = new Date(date);
             }
         }
-        if(!date instanceof Date) date = new Date(date);
-        if(!date instanceof Date) return nullValue;
-        if(typeof date.getFullYear === 'undefined') return nullValue;
-        if(date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
-        return date.getFullYear() + seperate + (date.getMonth() + 1 + '').padStart(2, '0') + seperate + (date.getDate() + '').padStart(2, '0');
-    },
-    
-    toDateTimeString: (date = new Date(), nullValue='', seperate='-', timeSeperate=':') => {
-        if(!date) return nullValue;
-        if(typeof date === 'string') {
-            if(date.split('T').length == 2 && date.indexOf('Z') == -1) {
+        if (!date instanceof Date) date = new Date(date);
+        if (!date instanceof Date) return nullValue;
+        if (typeof date.getFullYear === 'undefined') return nullValue;
+        if (date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
+        return (
+            date.getFullYear() + seperate + (date.getMonth() + 1 + '').padStart(2, '0') + seperate + (date.getDate() + '').padStart(2, '0')
+        );
+    },
+
+    toDateTimeString: (date = new Date(), nullValue = '', seperate = '-', timeSeperate = ':') => {
+        if (!date) return nullValue;
+        if (typeof date === 'string') {
+            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                 const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                 const matches = regexp.exec(date);
-                date = new Date(matches[1], parseInt(matches[2]) - 1, matches[3], matches[4], matches[5], matches[6], (matches[7] ? matches[7] : 0));
+                date = new Date(
+                    matches[1],
+                    parseInt(matches[2]) - 1,
+                    matches[3],
+                    matches[4],
+                    matches[5],
+                    matches[6],
+                    matches[7] ? matches[7] : 0,
+                );
             } else {
                 date = new Date(date);
             }
         }
-        if(!date instanceof Date) date = new Date(date);
-        if(!date instanceof Date) return nullValue;
-        if(typeof date.getFullYear === 'undefined') return nullValue;
-        if(date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
+        if (!date instanceof Date) date = new Date(date);
+        if (!date instanceof Date) return nullValue;
+        if (typeof date.getFullYear === 'undefined') return nullValue;
+        if (date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
         let result = '';
-        result += date.getFullYear() 
-            + seperate + (date.getMonth() + 1 + '').padStart(2, '0') 
-            + seperate + (date.getDate() + '').padStart(2, '0') 
-            + ' ' + (date.getHours() + '').padStart(2, '0') 
-            + timeSeperate + (date.getMinutes() + '').padStart(2, '0')
-            + timeSeperate + (date.getSeconds() + '').padStart(2, '0');
+        result +=
+            date.getFullYear() +
+            seperate +
+            (date.getMonth() + 1 + '').padStart(2, '0') +
+            seperate +
+            (date.getDate() + '').padStart(2, '0') +
+            ' ' +
+            (date.getHours() + '').padStart(2, '0') +
+            timeSeperate +
+            (date.getMinutes() + '').padStart(2, '0') +
+            timeSeperate +
+            (date.getSeconds() + '').padStart(2, '0');
         return result;
     },
 
-    get: (obj, property, defaultValue=null) => {
+    get: (obj, property, defaultValue = null) => {
         return _.get(obj, property, defaultValue);
     },
 
@@ -132,8 +172,8 @@ export const Util = {
         return _.set(obj, property, value);
     },
 
-    nvl: (obj, nullValue='') => {
-        if(obj == null || obj === 'undefined') return nullValue;
+    nvl: (obj, nullValue = '') => {
+        if (obj == null || obj === 'undefined') return nullValue;
         return obj;
     },
 
@@ -141,46 +181,46 @@ export const Util = {
         return new Date(Util.getDateString(obj, property));
     },
 
-    getMonthString: (obj, property, seperate='-') => {
+    getMonthString: (obj, property, seperate = '-') => {
         const mv = moment(Util.get(obj, property, ''));
-        if(mv.isValid()) {
+        if (mv.isValid()) {
             return mv.format('YYYY') + seperate + mv.format('MM');
         } else {
             return '';
         }
     },
 
-    getDateString: (obj, property, seperate='-') => {
+    getDateString: (obj, property, seperate = '-') => {
         return Util.toDateString(Util.get(obj, property, ''), '', seperate);
     },
 
-    getDateTimeString: (obj, property, dateSeperate='-', timeSeperate=':') => {
+    getDateTimeString: (obj, property, dateSeperate = '-', timeSeperate = ':') => {
         return Util.toDateTimeString(Util.get(obj, property, ''), '', dateSeperate, timeSeperate);
     },
 
     addMonth: (number, date = new Date()) => {
-        return new Date(date.setMonth(date.getMonth()+number));
+        return new Date(date.setMonth(date.getMonth() + number));
     },
 
     addYear: (number, date = new Date()) => {
-        return new Date(date.setFullYear(date.getFullYear()+number));
+        return new Date(date.setFullYear(date.getFullYear() + number));
     },
 
     addDate: (number, date = new Date()) => {
         return new Date(date.setDate(date.getDate() + number));
     },
 
-    getFirstDate: (date = new Date())=>{
-        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0')  + '-01';        
+    getFirstDate: (date = new Date()) => {
+        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0') + '-01';
     },
-    getLastDate: (date = new Date())=>{
-        var lastDay = (new Date( date.getFullYear(), date.getMonth() + 1 , 0) ).getDate();
-        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0')  + '-' + (lastDay + '').padStart(2, '0');
+    getLastDate: (date = new Date()) => {
+        var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
+        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0') + '-' + (lastDay + '').padStart(2, '0');
     },
-    
+
     toPrice: (num) => {
         if (!num) return 0;
-        return (''+num).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
+        return ('' + num).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
     },
     toInt: (num) => {
         if (!num) return 0;
@@ -194,71 +234,71 @@ export const Util = {
     svg: (path, name) => {
         let svgPath = path;
         let svgName = name;
-        if(!path && !name) return null;
-        if(path && name == '{}') {
+        if (!path && !name) return null;
+        if (path && name == '{}') {
             let list = {};
-            for(let p of Object.keys(Svgs).filter(key => key.indexOf(path) == 0)) {
-                for(let name of Object.keys(Svgs[p])) {
-                    list[p+'/'+name] = Svgs[p][name];
+            for (let p of Object.keys(Svgs).filter((key) => key.indexOf(path) == 0)) {
+                for (let name of Object.keys(Svgs[p])) {
+                    list[p + '/' + name] = Svgs[p][name];
                 }
             }
             return list;
         }
-        if(path && name == '[]') {
+        if (path && name == '[]') {
             let list = [];
-            for(let p of Object.keys(Svgs).filter(key => key.indexOf(path) == 0)) {
-                for(let name of Object.keys(Svgs[p])) {
+            for (let p of Object.keys(Svgs).filter((key) => key.indexOf(path) == 0)) {
+                for (let name of Object.keys(Svgs[p])) {
                     list.push({
-                        Path: p+'/'+name,
-                        Svg: Svgs[p][name]
+                        Path: p + '/' + name,
+                        Svg: Svgs[p][name],
                     });
                 }
             }
             return list;
         }
-        if(typeof name === 'undefined') {
+        if (typeof name === 'undefined') {
             const idx = path.lastIndexOf('/');
-            if(idx == -1) {
+            if (idx == -1) {
                 svgPath = '/';
                 svgName = path;
             } else {
                 svgPath = path.substr(0, idx);
-                if(idx+1 >= path.length) svgName = '';
-                else svgName = path.substr(idx+1);
+                if (idx + 1 >= path.length) svgName = '';
+                else svgName = path.substr(idx + 1);
             }
         }
-        if(typeof Svgs[svgPath] === 'undefined') {
+        if (typeof Svgs[svgPath] === 'undefined') {
             return null;
         }
-        if(typeof svgName === 'undefined' || svgName == '') return null;
-        if(typeof Svgs[svgPath][svgName] === 'undefined') return null;
+        if (typeof svgName === 'undefined' || svgName == '') return null;
+        if (typeof Svgs[svgPath][svgName] === 'undefined') return null;
         return Svgs[svgPath][svgName];
     },
 
     undefined: (value) => {
-        if(typeof value === 'undefined') return true;
+        if (typeof value === 'undefined') return true;
         return false;
     },
 
     convertGridData: (data, numColumns) => {
         const numberOfFullRows = Math.floor(data.length / numColumns);
 
-        let numberOfElementsLastRow = data.length - (numberOfFullRows * numColumns);
+        let numberOfElementsLastRow = data.length - numberOfFullRows * numColumns;
         while (numberOfElementsLastRow !== numColumns) {
-            data.push({empty:true});
-            numberOfElementsLastRow ++;
+            data.push({ empty: true });
+            numberOfElementsLastRow++;
         }
 
         return data;
     },
 
-    navigate: (navigation, menu, parentid=null, params={}) => {
-        if(menu == null) return;
+    navigate: (navigation, menu, parentid = null, params = {}) => {
+        if (menu == null) return;
 
         const navigateAction = NavigationActions.navigate({
             routeName: menu.path,
-            action: NavigationActions.navigate({ 
-                routeName: 'Index', 
+            action: NavigationActions.navigate({
+                routeName: 'Index',
                 params: {
                     auth: menu.auth,
                     userinfo: session.getUserInfo(),
@@ -269,10 +309,10 @@ export const Util = {
                         path: menu.path,
                         icon: menu.icon,
                         id: menu.id,
-                        parentid: (parentid == null ? (menu.parent == null ? 0 : menu.parent.id) : parentid),
+                        parentid: parentid == null ? (menu.parent == null ? 0 : menu.parent.id) : parentid,
                     },
-                    ...params
-                } 
+                    ...params,
+                },
             }),
         });
         navigation.dispatch(navigateAction);
@@ -280,36 +320,48 @@ export const Util = {
 
     validPassword: (passwd) => {
         if (/^[0-9a-zA-Z#?!@$%^&*-_+=]{10,}$/.test(passwd) == false) {
-          return '비밀번호는 대문자, 소문자, 숫자, 특수문자로 10글자이상 입력해주세요';
+            return '비밀번호는 대문자, 소문자, 숫자, 특수문자로 10글자이상 입력해주세요';
         }
-      
+
         let typeCount = 0;
         for (let reg of [/[0-9]+/, /[a-z]+/, /[A-Z]+/, /[#?!@$%^&\*\-\/_+=]+/]) {
-          if (reg.test(passwd)) {
-            typeCount++;
-          }
+            if (reg.test(passwd)) {
+                typeCount++;
+            }
         }
-      
+
         if (typeCount < 2) {
-          return '대문자, 소문자, 숫자, 특수문자 중 2개 조합으로 작성해주세요';
+            return '대문자, 소문자, 숫자, 특수문자 중 2개 조합으로 작성해주세요';
         }
-      
+
         return null;
     },
 
     parseFloat: (value) => {
         let result = parseFloat(value);
-        if(isNaN(result)) {
+        if (isNaN(result)) {
             return 0;
         }
         return result;
     },
 
     downloadFile: (file) => {
-        if(file.Path && file.Name) {
-            Linking.openURL(`${Config.BASE_URL}/api/FileDownload/DownloadFile?filePath=${encodeURIComponent(file.Path)}&fileName=${encodeURIComponent(file.Name)}`);
+        if (file.Path && file.Name) {
+            Linking.openURL(
+                `${Config.BASE_URL}/api/FileDownload/DownloadFile?filePath=${encodeURIComponent(file.Path)}&fileName=${encodeURIComponent(
+                    file.Name,
+                )}`,
+            );
         } else {
             Linking.openURL(file.Url);
         }
     },
+
+    getMeasure: (component) => {
+        return new Promise((resolve, reject) => {
+            component.measure((x, y, width, height, pageX, pageY) => {
+                resolve({ x, y, width, height, pageX, pageY });
+            });
+        });
+    },
 };

+ 1 - 1
src/version.js

@@ -1 +1 @@
-export const version = '1.0.0.6';
+export const version = '1.0.0.21';

+ 29 - 15
yarn-error.log

@@ -1,5 +1,5 @@
 Arguments: 
-  C:\Program Files\nodejs\node.exe C:\Program Files (x86)\Yarn\bin\yarn.js add react-native-svg
+  C:\Program Files\nodejs\node.exe C:\Program Files (x86)\Yarn\bin\yarn.js add react-native-webview@9.4.0
 
 PATH: 
   C:\Program Files\ImageMagick-7.0.9-Q16;C:\Python27\;C:\Python27\Scripts;C:\Program Files (x86)\Windows Resource Kits\Tools\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\ManagementStudio\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\120\DTS\Binn\;C:\Program Files\Microsoft SQL Server\120\DTS\Binn\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files\Microsoft\Web Platform Installer\;c:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;C:\Program Files\Git\cmd;C:\Program Files\dotnet\;C:\ProgramData\chocolatey\bin;C:\Program Files\Java\jdk1.8.0_231\bin;D:\Users\Administrator\AppData\Local\Android\sdk\platform-tools-delete;C:\Program Files\Java\jdk1.8.0_231\bin;C:\Program Files\nodejs\;C:\Program Files (x86)\Yarn\bin\;D:\Program Files\Nox\bin;C:\Program Files (x86)\Microsoft SQL Server\150\DTS\Binn\;C:\Program Files\TortoiseSVN\bin;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Bandizip\;C:\Users\Administrator\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\Administrator\.dotnet\tools;C:\Users\Administrator\AppData\Roaming\npm;C:\Users\Administrator\AppData\Local\Yarn\bin
@@ -14,16 +14,17 @@ Platform:
   win32 x64
 
 Trace: 
-  Error: EPERM: operation not permitted, unlink 'D:\Projects\FMS\fms-app-frontend\node_modules\@babel\generator\node_modules\.bin'
+  Error: EPERM: operation not permitted, unlink 'D:\Projects\FMS\fms-app-frontend\node_modules\@babel\plugin-transform-runtime\node_modules\.bin'
 
 npm manifest: 
   {
     "main": "node_modules/expo/AppEntry.js",
     "scripts": {
-      "start-cottus": "node scripts/screens.js && node scripts/images.js && node scripts/svgs.js && node scripts/lotties.js && node scripts/publish.js cottus && expo login -u cottus -p insave11 && expo start",
-      "start-hdc-icontrols": "node scripts/screens.js && node scripts/images.js && node scripts/svgs.js && node scripts/lotties.js && node scripts/publish.js hdc-icontrols && expo login -u hdc-icontrols -p icontrols123., && expo start",
-      "start-fronnix": "node scripts/screens.js && node scripts/images.js && node scripts/svgs.js && node scripts/lotties.js && node scripts/publish.js fronnix && expo login -u fronnix -p 1999035 && expo start",
-      "start": "node scripts/screens.js && node scripts/images.js && node scripts/svgs.js && node scripts/lotties.js && expo start",
+      "start-hdc-icontrols": "node scripts/screens.js && node scripts/svgs.js && node scripts/increase_version.js && node scripts/publish.js hdc-icontrols && expo login -u hdc-icontrols -p icontrols123., && expo start",
+      "start-fronnix": "node scripts/screens.js && node scripts/svgs.js && node scripts/publish.js fronnix && expo login -u fronnix -p 1999035 && expo start",
+      "start-cottus": "node scripts/screens.js && node scripts/svgs.js && node scripts/publish.js cottus && expo login -u cottus -p insave11 && expo start",
+      "start": "node scripts/screens.js && node scripts/svgs.js && expo start",
+      "increase-version": "node scripts/increase_version.js",
       "android": "expo start --android",
       "ios": "expo start --ios",
       "web": "expo start --web",
@@ -62,6 +63,7 @@ npm manifest:
       "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
       "react-native-calendars": "^1.261.0",
       "react-native-elements": "^1.2.7",
+      "react-native-final-tree-view": "^2.0.3",
       "react-native-gesture-handler": "~1.6.0",
       "react-native-image-pan-zoom": "^2.1.11",
       "react-native-image-zoom-viewer": "^2.2.27",
@@ -71,7 +73,7 @@ npm manifest:
       "react-native-safe-area-context": "~3.0.7",
       "react-native-safe-area-view": "^1.0.0",
       "react-native-screens": "~2.9.0",
-      "react-native-svg": "12.1.0",
+      "react-native-svg": "9.13.3",
       "react-native-svg-animations": "^0.1.9",
       "react-native-vector-icons": "^6.6.0",
       "react-native-web": "~0.11.7",
@@ -2916,7 +2918,7 @@ Lockfile:
     resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
     integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==
   
-  css-select@^2.0.0, css-select@^2.1.0:
+  css-select@^2.0.0, css-select@^2.0.2:
     version "2.1.0"
     resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef"
     integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==
@@ -2943,7 +2945,7 @@ Lockfile:
       mdn-data "2.0.4"
       source-map "^0.6.1"
   
-  css-tree@^1.0.0-alpha.39:
+  css-tree@^1.0.0-alpha.37:
     version "1.0.0-alpha.39"
     resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
     integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
@@ -5339,6 +5341,11 @@ Lockfile:
     dependencies:
       p-locate "^4.1.0"
   
+  lodash.get@^4.4.2:
+    version "4.4.2"
+    resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+    integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
+  
   lodash.throttle@^4.1.1:
     version "4.1.1"
     resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
@@ -7004,6 +7011,13 @@ Lockfile:
       react-native-ratings "^6.3.0"
       react-native-status-bar-height "^2.2.0"
   
+  react-native-final-tree-view@^2.0.3:
+    version "2.0.3"
+    resolved "https://registry.yarnpkg.com/react-native-final-tree-view/-/react-native-final-tree-view-2.0.3.tgz#2909539d4caa2d8e312cf7b3ba8d30b5d0c4906f"
+    integrity sha512-pQ5j8fJi+OEfd3cFBD3OSwbwIUElJeHZh6Mxa2tW2SSj26R5ybAtCg91ZkvE3wnS3hFe4rPu384O6KlayowmHA==
+    dependencies:
+      lodash.get "^4.4.2"
+  
   react-native-gesture-handler@~1.6.0:
     version "1.6.1"
     resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.6.1.tgz#678e2dce250ed66e93af409759be22cd6375dd17"
@@ -7124,13 +7138,13 @@ Lockfile:
       path-dirname "^1.0.2"
       semver "^5.6.0"
   
-  react-native-svg@12.1.0:
-    version "12.1.0"
-    resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-12.1.0.tgz#acfe48c35cd5fca3d5fd767abae0560c36cfc03d"
-    integrity sha512-1g9qBRci7man8QsHoXn6tP3DhCDiypGgc6+AOWq+Sy+PmP6yiyf8VmvKuoqrPam/tf5x+ZaBT2KI0gl7bptZ7w==
+  react-native-svg@9.13.3:
+    version "9.13.3"
+    resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-9.13.3.tgz#6414b337d55af169ac2487ab70f3108404434446"
+    integrity sha512-H50b2m4jvrQ7KxKs8uYSuWecr6e5XC7BDfS7DaA96+0Owjh0C9DksI5l8SRyHnmE+emiYMPu6Qqfr9dCyKkaJQ==
     dependencies:
-      css-select "^2.1.0"
-      css-tree "^1.0.0-alpha.39"
+      css-select "^2.0.2"
+      css-tree "^1.0.0-alpha.37"
   
   react-native-swipe-gestures@^1.0.3:
     version "1.0.5"

+ 54 - 19
yarn.lock

@@ -64,14 +64,13 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
-"@babel/generator@^7.0.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7":
-  version "7.7.7"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45"
-  integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==
+"@babel/generator@^7.0.0":
+  version "7.11.6"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620"
+  integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==
   dependencies:
-    "@babel/types" "^7.7.4"
+    "@babel/types" "^7.11.5"
     jsesc "^2.5.1"
-    lodash "^4.17.13"
     source-map "^0.5.0"
 
 "@babel/generator@^7.10.4", "@babel/generator@^7.5.0":
@@ -84,6 +83,16 @@
     lodash "^4.17.13"
     source-map "^0.5.0"
 
+"@babel/generator@^7.7.4", "@babel/generator@^7.7.7":
+  version "7.7.7"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45"
+  integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+    jsesc "^2.5.1"
+    lodash "^4.17.13"
+    source-map "^0.5.0"
+
 "@babel/generator@^7.8.0":
   version "7.8.0"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.0.tgz#40a1244677be58ffdc5cd01e22634cd1d5b29edf"
@@ -138,6 +147,18 @@
     "@babel/helper-replace-supers" "^7.10.4"
     "@babel/helper-split-export-declaration" "^7.10.4"
 
+"@babel/helper-create-class-features-plugin@^7.10.5":
+  version "7.10.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d"
+  integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==
+  dependencies:
+    "@babel/helper-function-name" "^7.10.4"
+    "@babel/helper-member-expression-to-functions" "^7.10.5"
+    "@babel/helper-optimise-call-expression" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-replace-supers" "^7.10.4"
+    "@babel/helper-split-export-declaration" "^7.10.4"
+
 "@babel/helper-create-class-features-plugin@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d"
@@ -237,6 +258,13 @@
   dependencies:
     "@babel/types" "^7.10.4"
 
+"@babel/helper-member-expression-to-functions@^7.10.5":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df"
+  integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==
+  dependencies:
+    "@babel/types" "^7.11.0"
+
 "@babel/helper-member-expression-to-functions@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74"
@@ -624,13 +652,6 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.10.4"
 
-"@babel/plugin-syntax-typescript@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz#5d037ffa10f3b25a16f32570ebbe7a8c2efa304b"
-  integrity sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.0.0"
-
 "@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12"
@@ -917,13 +938,13 @@
     "@babel/helper-plugin-utils" "^7.0.0"
 
 "@babel/plugin-transform-typescript@^7.0.0":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz#2974fd05f4e85c695acaf497f432342de9fc0636"
-  integrity sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg==
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb"
+  integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.7.4"
-    "@babel/helper-plugin-utils" "^7.0.0"
-    "@babel/plugin-syntax-typescript" "^7.7.4"
+    "@babel/helper-create-class-features-plugin" "^7.10.5"
+    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/plugin-syntax-typescript" "^7.10.4"
 
 "@babel/plugin-transform-typescript@^7.5.0":
   version "7.10.4"
@@ -1115,6 +1136,15 @@
     lodash "^4.17.13"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.11.0", "@babel/types@^7.11.5":
+  version "7.11.5"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
+  integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.10.4"
+    lodash "^4.17.19"
+    to-fast-properties "^2.0.0"
+
 "@babel/types@^7.4.4", "@babel/types@^7.8.0":
   version "7.8.0"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.0.tgz#1a2039a028057a2c888b668d94c98e61ea906e7f"
@@ -5241,6 +5271,11 @@ lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.1
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 
+lodash@^4.17.19:
+  version "4.17.20"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+  integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+
 log-symbols@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov