Index: Gruntfile.js =================================================================== diff -u -r82fb2115fafe0316ea01d4360be279ca54db346f -r5da903dc373b853ae7b5b77d2e48b7ea1710633d --- Gruntfile.js (.../Gruntfile.js) (revision 82fb2115fafe0316ea01d4360be279ca54db346f) +++ Gruntfile.js (.../Gruntfile.js) (revision 5da903dc373b853ae7b5b77d2e48b7ea1710633d) @@ -1,349 +1,395 @@ -// AdminLTE Gruntfile -module.exports = function (grunt) { // jshint ignore:line - 'use strict'; +module.exports = function (grunt) { + "use strict"; - grunt.initConfig({ - pkg : grunt.file.readJSON('package.json'), - connect:{ - server: { - options: { - port:9999, - hostname: '0.0.0.0', - middleware: function (connect, options, defaultMiddleware) { - var proxy = require('grunt-connect-proxy/lib/utils').proxyRequest; - return [ - // Include the proxy first - proxy - ].concat(defaultMiddleware); - } - }, - proxies: [ - { - context: ['/auth-anon','/auth-user','/auth-admin','/auth-check','/sso','/dwr','/logout'], - host: 'localhost', - port: 13131, - https: false, - changeOrigin: true - } - ] - }, - }, - watch : { - less : { - // Compiles less files upon saving - files: ['build/less/*.less'], - tasks: ['less:development', 'less:production', 'replace', 'notify:less'] - }, - js : { - // Compile js files upon saving - files: ['build/js/*.js'], - tasks: ['js', 'notify:js'] - }, - skins: { - // Compile any skin less files upon saving - files: ['build/less/skins/*.less'], - tasks: ['less:skins', 'less:minifiedSkins', 'notify:less'] - } - }, - // Notify end of tasks - notify: { - less: { - options: { - title : 'AdminLTE', - message: 'LESS finished running' - } - }, - js : { - options: { - title : 'AdminLTE', - message: 'JS bundler finished running' - } - } - }, - // 'less'-task configuration - // This task will compile all less files upon saving to create both AdminLTE.css and AdminLTE.min.css - less : { - // Development not compressed - development : { - files: { - // compilation.css : source.less - 'dist/css/AdminLTE.css' : 'build/less/AdminLTE.less', - // AdminLTE without plugins - 'dist/css/alt/AdminLTE-without-plugins.css' : 'build/less/AdminLTE-without-plugins.less', - // Separate plugins - 'dist/css/alt/AdminLTE-select2.css' : 'build/less/select2.less', - 'dist/css/alt/AdminLTE-fullcalendar.css' : 'build/less/fullcalendar.less', - 'dist/css/alt/AdminLTE-bootstrap-social.css': 'build/less/bootstrap-social.less' - } - }, - // Production compressed version - production : { - options: { - compress: true - }, - files : { - // compilation.css : source.less - 'dist/css/AdminLTE.min.css' : 'build/less/AdminLTE.less', - // AdminLTE without plugins - 'dist/css/alt/AdminLTE-without-plugins.min.css' : 'build/less/AdminLTE-without-plugins.less', - // Separate plugins - 'dist/css/alt/AdminLTE-select2.min.css' : 'build/less/select2.less', - 'dist/css/alt/AdminLTE-fullcalendar.min.css' : 'build/less/fullcalendar.less', - 'dist/css/alt/AdminLTE-bootstrap-social.min.css': 'build/less/bootstrap-social.less' - } - }, - // Non minified skin files - skins : { - files: { - 'dist/css/skins/skin-blue.css' : 'build/less/skins/skin-blue.less', - 'dist/css/skins/skin-black.css' : 'build/less/skins/skin-black.less', - 'dist/css/skins/skin-yellow.css' : 'build/less/skins/skin-yellow.less', - 'dist/css/skins/skin-green.css' : 'build/less/skins/skin-green.less', - 'dist/css/skins/skin-red.css' : 'build/less/skins/skin-red.less', - 'dist/css/skins/skin-purple.css' : 'build/less/skins/skin-purple.less', - 'dist/css/skins/skin-blue-light.css' : 'build/less/skins/skin-blue-light.less', - 'dist/css/skins/skin-black-light.css' : 'build/less/skins/skin-black-light.less', - 'dist/css/skins/skin-yellow-light.css': 'build/less/skins/skin-yellow-light.less', - 'dist/css/skins/skin-green-light.css' : 'build/less/skins/skin-green-light.less', - 'dist/css/skins/skin-red-light.css' : 'build/less/skins/skin-red-light.less', - 'dist/css/skins/skin-purple-light.css': 'build/less/skins/skin-purple-light.less', - 'dist/css/skins/_all-skins.css' : 'build/less/skins/_all-skins.less' - } - }, - // Skins minified - minifiedSkins: { - options: { - compress: true - }, - files : { - 'dist/css/skins/skin-blue.min.css' : 'build/less/skins/skin-blue.less', - 'dist/css/skins/skin-black.min.css' : 'build/less/skins/skin-black.less', - 'dist/css/skins/skin-yellow.min.css' : 'build/less/skins/skin-yellow.less', - 'dist/css/skins/skin-green.min.css' : 'build/less/skins/skin-green.less', - 'dist/css/skins/skin-red.min.css' : 'build/less/skins/skin-red.less', - 'dist/css/skins/skin-purple.min.css' : 'build/less/skins/skin-purple.less', - 'dist/css/skins/skin-blue-light.min.css' : 'build/less/skins/skin-blue-light.less', - 'dist/css/skins/skin-black-light.min.css' : 'build/less/skins/skin-black-light.less', - 'dist/css/skins/skin-yellow-light.min.css': 'build/less/skins/skin-yellow-light.less', - 'dist/css/skins/skin-green-light.min.css' : 'build/less/skins/skin-green-light.less', - 'dist/css/skins/skin-red-light.min.css' : 'build/less/skins/skin-red-light.less', - 'dist/css/skins/skin-purple-light.min.css': 'build/less/skins/skin-purple-light.less', - 'dist/css/skins/_all-skins.min.css' : 'build/less/skins/_all-skins.less' - } - } - }, + grunt.initConfig({ + pkg: grunt.file.readJSON("package.json"), + connect: { + server: { + options: { + //외부에서 개발 + port: 80, + //내부에서 개발 + //port: 9999, + hostname: "0.0.0.0", + middleware: function (connect, options, defaultMiddleware) { + defaultMiddleware.unshift(function (req, res, next) { + res.setHeader("Access-Control-Allow-Credentials", true); + res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); + res.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS"); + if (req.url.startsWith("/reference/drawdb/editor")) { + req.url = "/reference/drawdb/index.html"; + } else if (req.url.startsWith("/reference/drawdb/templates")) { + req.url = "/reference/drawdb/index.html"; + } else if (req.url.startsWith("/reference/drawdb/survey")) { + req.url = "/reference/drawdb/index.html"; + } else if (req.url.startsWith("/reference/drawdb/shortcuts")) { + req.url = "/reference/drawdb/index.html"; + } + if (req.method.toUpperCase() == "POST") req.method = "GET"; + return next(); + }); - // Uglify task info. Compress the js files. - uglify: { - options : { - mangle : true, - output: { - comments: 'some' - }, - }, - production: { - files: { - 'dist/js/adminlte.min.js': ['dist/js/adminlte.js'] - } - } - }, + var proxy = require("grunt-connect-proxy/lib/utils").proxyRequest; + return [ + // Include the proxy first + proxy + ].concat(defaultMiddleware); + } + }, + //로컬 개발 및 테스트용 + // proxies: [ + // { + // context: ['/auth-anon', '/auth-user', '/auth-admin', '/auth-check', '/auth-sche', '/sso', '/dwr', '/logout', '/login', '/oauth2', '/arms-check', + // '/swagger-ui.html', '/swagger-ui', '/webjars', '/swagger-resources', '/v2', '/engine-search-api'], + // host: '127.0.0.1', + // port: 13131, + // https: false, + // changeOrigin: true + // } + // ] + // 외부에서 개발 + proxies: [ + { + context: [ + "/auth-anon", + "/auth-user", + "/auth-admin", + "/auth-check", + "/auth-sche", + "/engine-search-api", + "/sso", + "/dwr", + "/logout", + "/login", + "/oauth2", + "/arms-check", + "/swagger-ui.html", + "/swagger-ui", + "/webjars", + "/swagger-resources", + "/v2", + "/php", + ], + host: "www.313.co.kr", + port: 80, + https: false, + changeOrigin: true + } + ] + } + }, + watch: { + less: { + // Compiles less files upon saving + files: ["build/less/*.less"], + tasks: ["less:development", "less:production", "replace", "notify:less"] + }, + js: { + // Compile js files upon saving + files: ["build/js/*.js"], + tasks: ["js", "notify:js"] + }, + skins: { + // Compile any skin less files upon saving + files: ["build/less/skins/*.less"], + tasks: ["less:skins", "less:minifiedSkins", "notify:less"] + } + }, + // Notify end of tasks + notify: { + less: { + options: { + title: "AdminLTE", + message: "LESS finished running" + } + }, + js: { + options: { + title: "AdminLTE", + message: "JS bundler finished running" + } + } + }, + // 'less'-task configuration + // This task will compile all less files upon saving to create both AdminLTE.css and AdminLTE.min.css + less: { + // Development not compressed + development: { + files: { + // compilation.css : source.less + "dist/css/AdminLTE.css": "build/less/AdminLTE.less", + // AdminLTE without plugins + "dist/css/alt/AdminLTE-without-plugins.css": "build/less/AdminLTE-without-plugins.less", + // Separate plugins + "dist/css/alt/AdminLTE-select2.css": "build/less/select2.less", + "dist/css/alt/AdminLTE-fullcalendar.css": "build/less/fullcalendar.less", + "dist/css/alt/AdminLTE-bootstrap-social.css": "build/less/bootstrap-social.less" + } + }, + // Production compressed version + production: { + options: { + compress: true + }, + files: { + // compilation.css : source.less + "dist/css/AdminLTE.min.css": "build/less/AdminLTE.less", + // AdminLTE without plugins + "dist/css/alt/AdminLTE-without-plugins.min.css": "build/less/AdminLTE-without-plugins.less", + // Separate plugins + "dist/css/alt/AdminLTE-select2.min.css": "build/less/select2.less", + "dist/css/alt/AdminLTE-fullcalendar.min.css": "build/less/fullcalendar.less", + "dist/css/alt/AdminLTE-bootstrap-social.min.css": "build/less/bootstrap-social.less" + } + }, + // Non minified skin files + skins: { + files: { + "dist/css/skins/skin-blue.css": "build/less/skins/skin-blue.less", + "dist/css/skins/skin-black.css": "build/less/skins/skin-black.less", + "dist/css/skins/skin-yellow.css": "build/less/skins/skin-yellow.less", + "dist/css/skins/skin-green.css": "build/less/skins/skin-green.less", + "dist/css/skins/skin-red.css": "build/less/skins/skin-red.less", + "dist/css/skins/skin-purple.css": "build/less/skins/skin-purple.less", + "dist/css/skins/skin-blue-light.css": "build/less/skins/skin-blue-light.less", + "dist/css/skins/skin-black-light.css": "build/less/skins/skin-black-light.less", + "dist/css/skins/skin-yellow-light.css": "build/less/skins/skin-yellow-light.less", + "dist/css/skins/skin-green-light.css": "build/less/skins/skin-green-light.less", + "dist/css/skins/skin-red-light.css": "build/less/skins/skin-red-light.less", + "dist/css/skins/skin-purple-light.css": "build/less/skins/skin-purple-light.less", + "dist/css/skins/_all-skins.css": "build/less/skins/_all-skins.less" + } + }, + // Skins minified + minifiedSkins: { + options: { + compress: true + }, + files: { + "dist/css/skins/skin-blue.min.css": "build/less/skins/skin-blue.less", + "dist/css/skins/skin-black.min.css": "build/less/skins/skin-black.less", + "dist/css/skins/skin-yellow.min.css": "build/less/skins/skin-yellow.less", + "dist/css/skins/skin-green.min.css": "build/less/skins/skin-green.less", + "dist/css/skins/skin-red.min.css": "build/less/skins/skin-red.less", + "dist/css/skins/skin-purple.min.css": "build/less/skins/skin-purple.less", + "dist/css/skins/skin-blue-light.min.css": "build/less/skins/skin-blue-light.less", + "dist/css/skins/skin-black-light.min.css": "build/less/skins/skin-black-light.less", + "dist/css/skins/skin-yellow-light.min.css": "build/less/skins/skin-yellow-light.less", + "dist/css/skins/skin-green-light.min.css": "build/less/skins/skin-green-light.less", + "dist/css/skins/skin-red-light.min.css": "build/less/skins/skin-red-light.less", + "dist/css/skins/skin-purple-light.min.css": "build/less/skins/skin-purple-light.less", + "dist/css/skins/_all-skins.min.css": "build/less/skins/_all-skins.less" + } + } + }, - // Concatenate JS Files - concat: { - options: { - separator: '\n\n', - banner : '/*! AdminLTE app.js\n' - + '* ================\n' - + '* Main JS application file for AdminLTE v2. This file\n' - + '* should be included in all pages. It controls some layout\n' - + '* options and implements exclusive AdminLTE plugins.\n' - + '*\n' - + '* @author Colorlib\n' - + '* @support \n' - + '* @version <%= pkg.version %>\n' - + '* @repository <%= pkg.repository.url %>\n' - + '* @license MIT \n' - + '*/\n\n' - + '// Make sure jQuery has been loaded\n' - + 'if (typeof jQuery === \'undefined\') {\n' - + 'throw new Error(\'AdminLTE requires jQuery\')\n' - + '}\n\n' - }, - dist : { - src : [ - 'build/js/BoxRefresh.js', - 'build/js/BoxWidget.js', - 'build/js/ControlSidebar.js', - 'build/js/DirectChat.js', - 'build/js/PushMenu.js', - 'build/js/TodoList.js', - 'build/js/Tree.js', - 'build/js/Layout.js', - ], - dest: 'dist/js/adminlte.js' - } - }, + // Uglify task info. Compress the js files. + uglify: { + options: { + mangle: true, + output: { + comments: "some" + } + }, + production: { + files: { + "dist/js/adminlte.min.js": ["dist/js/adminlte.js"] + } + } + }, - // Replace image paths in AdminLTE without plugins - replace: { - withoutPlugins : { - src : ['dist/css/alt/AdminLTE-without-plugins.css'], - dest : 'dist/css/alt/AdminLTE-without-plugins.css', - replacements: [ - { - from: '../img', - to : '../../img' - } - ] - }, - withoutPluginsMin: { - src : ['dist/css/alt/AdminLTE-without-plugins.min.css'], - dest : 'dist/css/alt/AdminLTE-without-plugins.min.css', - replacements: [ - { - from: '../img', - to : '../../img' - } - ] - } - }, + // Concatenate JS Files + concat: { + options: { + separator: "\n\n", + banner: + "/*! AdminLTE app.js\n" + + "* ================\n" + + "* Main JS application file for AdminLTE v2. This file\n" + + "* should be included in all pages. It controls some layout\n" + + "* options and implements exclusive AdminLTE plugins.\n" + + "*\n" + + "* @author Colorlib\n" + + "* @support \n" + + "* @version <%= pkg.version %>\n" + + "* @repository <%= pkg.repository.url %>\n" + + "* @license MIT \n" + + "*/\n\n" + + "// Make sure jQuery has been loaded\n" + + "if (typeof jQuery === 'undefined') {\n" + + "throw new Error('AdminLTE requires jQuery')\n" + + "}\n\n" + }, + dist: { + src: [ + "build/js/BoxRefresh.js", + "build/js/BoxWidget.js", + "build/js/ControlSidebar.js", + "build/js/DirectChat.js", + "build/js/PushMenu.js", + "build/js/TodoList.js", + "build/js/Tree.js", + "build/js/Layout.js" + ], + dest: "dist/js/adminlte.js" + } + }, - // Build the documentation files - includes: { - build: { - src : ['*.html'], // Source files - dest : 'documentation/', // Destination directory - flatten: true, - cwd : 'documentation/build', - options: { - silent : true, - includePath: 'documentation/build/include' - } - } - }, + // Replace image paths in AdminLTE without plugins + replace: { + withoutPlugins: { + src: ["dist/css/alt/AdminLTE-without-plugins.css"], + dest: "dist/css/alt/AdminLTE-without-plugins.css", + replacements: [ + { + from: "../img", + to: "../../img" + } + ] + }, + withoutPluginsMin: { + src: ["dist/css/alt/AdminLTE-without-plugins.min.css"], + dest: "dist/css/alt/AdminLTE-without-plugins.min.css", + replacements: [ + { + from: "../img", + to: "../../img" + } + ] + } + }, - // Optimize images - image: { - dynamic: { - files: [ - { - expand: true, - cwd : 'build/img/', - src : ['**/*.{png,jpg,gif,svg,jpeg}'], - dest : 'dist/img/' - } - ] - } - }, + // Build the documentation files + includes: { + build: { + src: ["*.html"], // Source files + dest: "documentation/", // Destination directory + flatten: true, + cwd: "documentation/build", + options: { + silent: true, + includePath: "documentation/build/include" + } + } + }, - // Validate JS code - jshint: { - options: { - jshintrc: 'build/js/.jshintrc' - }, - grunt : { - options: { - jshintrc: 'build/grunt/.jshintrc' - }, - src : 'Gruntfile.js' - }, - core : { - src: 'build/js/*.js' - }, - demo : { - src: 'dist/js/demo.js' - }, - pages : { - src: 'dist/js/pages/*.js' - } - }, + // Optimize images + image: { + dynamic: { + files: [ + { + expand: true, + cwd: "build/img/", + src: ["**/*.{png,jpg,gif,svg,jpeg}"], + dest: "dist/img/" + } + ] + } + }, - jscs: { - options: { - config: 'build/js/.jscsrc' - }, - core : { - src: '<%= jshint.core.src %>' - }, - pages : { - src: '<%= jshint.pages.src %>' - } - }, + // Validate JS code + jshint: { + options: { + jshintrc: "build/js/.jshintrc" + }, + grunt: { + options: { + jshintrc: "build/grunt/.jshintrc" + }, + src: "Gruntfile.js" + }, + core: { + src: "build/js/*.js" + }, + demo: { + src: "dist/js/demo.js" + }, + pages: { + src: "dist/js/pages/*.js" + } + }, - // Validate CSS files - csslint: { - options: { - csslintrc: 'build/less/.csslintrc' - }, - dist : [ - 'dist/css/AdminLTE.css' - ] - }, + jscs: { + options: { + config: "build/js/.jscsrc" + }, + core: { + src: "<%= jshint.core.src %>" + }, + pages: { + src: "<%= jshint.pages.src %>" + } + }, - // Validate Bootstrap HTML - bootlint: { - options: { - relaxerror: ['W005'] - }, - files : ['pages/**/*.html', '*.html'] - }, + // Validate CSS files + csslint: { + options: { + csslintrc: "build/less/.csslintrc" + }, + dist: ["dist/css/AdminLTE.css"] + }, - // Delete images in build directory - // After compressing the images in the build/img dir, there is no need - // for them - clean: { - build: ['build/img/*'] - } - }); + // Validate Bootstrap HTML + bootlint: { + options: { + relaxerror: ["W005"] + }, + files: ["pages/**/*.html", "*.html"] + }, - // Load all grunt tasks + // Delete images in build directory + // After compressing the images in the build/img dir, there is no need + // for them + clean: { + build: ["build/img/*"] + } + }); - // LESS Compiler - grunt.loadNpmTasks('grunt-contrib-less'); - // Watch File Changes - grunt.loadNpmTasks('grunt-contrib-watch'); - // Compress JS Files - grunt.loadNpmTasks('grunt-contrib-uglify'); - // Include Files Within HTML - grunt.loadNpmTasks('grunt-includes'); - // Optimize images - grunt.loadNpmTasks('grunt-image'); - // Validate JS code - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-jscs'); - // Delete not needed files - grunt.loadNpmTasks('grunt-contrib-clean'); - // Lint CSS - grunt.loadNpmTasks('grunt-contrib-csslint'); - // Lint Bootstrap - grunt.loadNpmTasks('grunt-bootlint'); - // Concatenate JS files - grunt.loadNpmTasks('grunt-contrib-concat'); - // Notify - grunt.loadNpmTasks('grunt-notify'); - // Replace - grunt.loadNpmTasks('grunt-text-replace'); + // Load all grunt tasks - // Linting task - grunt.registerTask('lint', ['jshint', 'csslint', 'bootlint']); - // JS task - grunt.registerTask('js', ['concat', 'uglify']); - // CSS Task - grunt.registerTask('css', ['less:development', 'less:production', 'replace']); + // LESS Compiler + grunt.loadNpmTasks("grunt-contrib-less"); + // Watch File Changes + grunt.loadNpmTasks("grunt-contrib-watch"); + // Compress JS Files + grunt.loadNpmTasks("grunt-contrib-uglify"); + // Include Files Within HTML + grunt.loadNpmTasks("grunt-includes"); + // Optimize images + grunt.loadNpmTasks("grunt-image"); + // Validate JS code + grunt.loadNpmTasks("grunt-contrib-jshint"); + grunt.loadNpmTasks("grunt-jscs"); + // Delete not needed files + grunt.loadNpmTasks("grunt-contrib-clean"); + // Lint CSS + grunt.loadNpmTasks("grunt-contrib-csslint"); + // Lint Bootstrap + grunt.loadNpmTasks("grunt-bootlint"); + // Concatenate JS files + grunt.loadNpmTasks("grunt-contrib-concat"); + // Notify + grunt.loadNpmTasks("grunt-notify"); + // Replace + grunt.loadNpmTasks("grunt-text-replace"); - // The default task (running 'grunt' in console) is 'watch' - grunt.registerTask('default', ['watch']); + // Linting task + grunt.registerTask("lint", ["jshint", "csslint", "bootlint"]); + // JS task + grunt.registerTask("js", ["concat", "uglify"]); + // CSS Task + grunt.registerTask("css", ["less:development", "less:production", "replace"]); - //313devgrp - grunt.loadNpmTasks('grunt-contrib-connect'); - grunt.loadNpmTasks('grunt-connect-proxy'); - grunt.loadNpmTasks('configureProxies:server'); - grunt.loadNpmTasks('grunt-contrib-compass'); - //grunt.registerTask('server', ['connect:server:keepalive']); - grunt.registerTask('server', function (target) { - grunt.task.run([ - 'configureProxies:server', - 'connect:server:keepalive' - ]); - }); + // The default task (running 'grunt' in console) is 'watch' + grunt.registerTask("default", ["watch"]); + + //313DEVGRP + grunt.loadNpmTasks("grunt-contrib-connect"); + grunt.loadNpmTasks("grunt-connect-proxy"); + grunt.loadNpmTasks("configureProxies:server"); + grunt.loadNpmTasks("grunt-contrib-compass"); + //grunt.registerTask('server', ['connect:server:keepalive']); + grunt.registerTask("server", function (target) { + grunt.task.run(["configureProxies:server", "connect:server:keepalive"]); + }); }; Index: reference/drawdb/README.md =================================================================== diff -u -rb7ea66ef2e1916cc3a77f525ba31656f6e0dea4f -r5da903dc373b853ae7b5b77d2e48b7ea1710633d --- reference/drawdb/README.md (.../README.md) (revision b7ea66ef2e1916cc3a77f525ba31656f6e0dea4f) +++ reference/drawdb/README.md (.../README.md) (revision 5da903dc373b853ae7b5b77d2e48b7ea1710633d) @@ -2,6 +2,12 @@ ## 1. reference/drawdb/source 경로로 이동 -## 2. npm run build or vite build 실행 +## 2. npm install +## 3-1. 개발 환경 - npm run dev + +http://localhost:5173/reference/drawdb/ 확인 + +## 3-2. 작업 후 빌드 - npm run build 실행 + /reference/drawdb/ 하위에 build 결과 파일이 생성된다. Index: reference/drawdb/source/src/components/EditorHeader/ControlPanel.jsx =================================================================== diff -u -rb7ea66ef2e1916cc3a77f525ba31656f6e0dea4f -r5da903dc373b853ae7b5b77d2e48b7ea1710633d --- reference/drawdb/source/src/components/EditorHeader/ControlPanel.jsx (.../ControlPanel.jsx) (revision b7ea66ef2e1916cc3a77f525ba31656f6e0dea4f) +++ reference/drawdb/source/src/components/EditorHeader/ControlPanel.jsx (.../ControlPanel.jsx) (revision 5da903dc373b853ae7b5b77d2e48b7ea1710633d) @@ -1521,7 +1521,7 @@ return (