| @@ -87,6 +87,8 @@ GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(fi | |||||
| WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) | WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) | ||||
| WEBPACK_CONFIGS := webpack.config.js | WEBPACK_CONFIGS := webpack.config.js | ||||
| WEBPACK_CONFIGS_TMP := webpack_temp.config.js | |||||
| WEBPACK_CONFIGS_PRO := webpack_pro.config.js | |||||
| WEBPACK_DEST := public/js/index.js public/css/index.css | WEBPACK_DEST := public/js/index.js public/css/index.css | ||||
| WEBPACK_DEST_DIRS := public/js public/css public/fonts | WEBPACK_DEST_DIRS := public/js public/css public/fonts | ||||
| @@ -290,7 +292,7 @@ lint-backend: golangci-lint revive vet swagger-check swagger-validate test-vendo | |||||
| .PHONY: lint-frontend | .PHONY: lint-frontend | ||||
| lint-frontend: node_modules | lint-frontend: node_modules | ||||
| npx eslint web_src/js webpack.config.js | |||||
| npx eslint web_src/js $(WEBPACK_CONFIGS) | |||||
| npx stylelint web_src/less | npx stylelint web_src/less | ||||
| .PHONY: watch-frontend | .PHONY: watch-frontend | ||||
| @@ -504,7 +506,7 @@ install: $(wildcard *.go) | |||||
| build: frontend backend | build: frontend backend | ||||
| .PHONY: frontend | .PHONY: frontend | ||||
| frontend: node-check $(FOMANTIC_DEST) $(WEBPACK_DEST) | |||||
| frontend: node-check webpack_prepare $(FOMANTIC_DEST) $(WEBPACK_DEST) webpack_end | |||||
| .PHONY: backend | .PHONY: backend | ||||
| backend: go-check generate $(EXECUTABLE) | backend: go-check generate $(EXECUTABLE) | ||||
| @@ -596,6 +598,19 @@ $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules | |||||
| .PHONY: webpack | .PHONY: webpack | ||||
| webpack: $(WEBPACK_DEST) | webpack: $(WEBPACK_DEST) | ||||
| webpack_prepare: | |||||
| if [ $(filter bindata,$(TAGS_SPLIT))x = "bindata"x ]; then \ | |||||
| echo "prepare"; \ | |||||
| cp $(WEBPACK_CONFIGS) $(WEBPACK_CONFIGS_TMP); \ | |||||
| cp $(WEBPACK_CONFIGS_PRO) $(WEBPACK_CONFIGS); \ | |||||
| fi | |||||
| webpack_end: | |||||
| if [ $(filter bindata,$(TAGS_SPLIT))x = "bindata"x ]; then \ | |||||
| echo "end"; \ | |||||
| mv $(WEBPACK_CONFIGS_TMP) $(WEBPACK_CONFIGS); \ | |||||
| fi | |||||
| $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules | $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules | ||||
| rm -rf $(WEBPACK_DEST_DIRS) | rm -rf $(WEBPACK_DEST_DIRS) | ||||
| @@ -114,7 +114,7 @@ socket.onmessage = function (e) { | |||||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>" | html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>" | ||||
| } | } | ||||
| else if(record.OpType == "9" || record.OpType == "5"){ | else if(record.OpType == "9" || record.OpType == "5"){ | ||||
| branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||||
| branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + encodeURI(record.RefName) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||||
| actionName = actionName.replace("{branch}",branch); | actionName = actionName.replace("{branch}",branch); | ||||
| html += recordPrefix + actionName; | html += recordPrefix + actionName; | ||||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | ||||
| @@ -156,20 +156,21 @@ socket.onmessage = function (e) { | |||||
| function getTaskLink(record){ | function getTaskLink(record){ | ||||
| var re = getRepoLink(record); | var re = getRepoLink(record); | ||||
| if(record.OpType == 24){ | if(record.OpType == 24){ | ||||
| return re + "/datasets?type=" + record.Content; | |||||
| re = re + "/datasets?type=" + record.Content; | |||||
| }else if(record.OpType == 25){ | }else if(record.OpType == 25){ | ||||
| return re + "/cloudbrain/" + record.Content; | |||||
| re = re + "/cloudbrain/" + record.RefName; | |||||
| }else if(record.OpType == 26){ | }else if(record.OpType == 26){ | ||||
| return re + "/modelarts/notebook/" + record.Content; | |||||
| re = re + "/modelarts/notebook/" + record.Content; | |||||
| }else if(record.OpType == 27){ | }else if(record.OpType == 27){ | ||||
| return re + "/modelarts/train-job/" + record.Content; | |||||
| re = re + "/modelarts/train-job/" + record.Content; | |||||
| }else if(record.OpType == 28){ | }else if(record.OpType == 28){ | ||||
| return re + "/modelarts/inference-job/" + record.Content; | |||||
| re = re + "/modelarts/inference-job/" + record.Content; | |||||
| }else if(record.OpType == 29){ | }else if(record.OpType == 29){ | ||||
| return re + "/cloudbrain/benchmark/" + record.Content; | |||||
| re = re + "/cloudbrain/benchmark/" + record.RefName; | |||||
| }else if(record.OpType == 30){ | }else if(record.OpType == 30){ | ||||
| return re + "/modelmanage/show_model_info?name=" + record.RefName; | |||||
| re = re + "/modelmanage/show_model_info?name=" + record.RefName; | |||||
| } | } | ||||
| re = encodeURI(re); | |||||
| return re; | return re; | ||||
| } | } | ||||
| @@ -184,7 +185,7 @@ function getMsg(record){ | |||||
| } | } | ||||
| html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">" | html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">" | ||||
| html += " <div class=\"middle aligned content nowrap\">" | html += " <div class=\"middle aligned content nowrap\">" | ||||
| html += " <a href=\"/" + name + "\" title=\"\">" + name + "</a>" | |||||
| html += " <a href=\"/" + encodeURI(name) + "\" title=\"\">" + name + "</a>" | |||||
| return html; | return html; | ||||
| } | } | ||||
| @@ -196,7 +197,7 @@ function getRepotext(record){ | |||||
| } | } | ||||
| } | } | ||||
| function getRepoLink(record){ | function getRepoLink(record){ | ||||
| return record.Repo.OwnerName + "/" + record.Repo.Name; | |||||
| return encodeURI(record.Repo.OwnerName + "/" + record.Repo.Name); | |||||
| } | } | ||||
| @@ -228,7 +229,7 @@ function getTime(UpdatedUnix,currentTime){ | |||||
| } | } | ||||
| function getPRLink(record){ | function getPRLink(record){ | ||||
| return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record); | |||||
| return encodeURI("/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record)); | |||||
| } | } | ||||
| function getPRText(record){ | function getPRText(record){ | ||||
| if(record.Repo.Alias){ | if(record.Repo.Alias){ | ||||
| @@ -241,7 +242,7 @@ function getPRText(record){ | |||||
| function getIssueLink(record){ | function getIssueLink(record){ | ||||
| return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record); | |||||
| return encodeURI("/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record)); | |||||
| } | } | ||||
| function getIssueId(record){ | function getIssueId(record){ | ||||
| @@ -512,7 +512,12 @@ func GetSuccessChunks(ctx *context.Context) { | |||||
| return | return | ||||
| } | } | ||||
| } else { | } else { | ||||
| isExist, err = storage.ObsHasObject(setting.BasePath + models.AttachmentRelativePath(fileChunk.UUID) + "/" + fileName) | |||||
| oldFileName := fileName | |||||
| oldAttachment, _ := models.GetAttachmentByUUID(fileChunk.UUID) | |||||
| if oldAttachment != nil { | |||||
| oldFileName = oldAttachment.Name | |||||
| } | |||||
| isExist, err = storage.ObsHasObject(setting.BasePath + models.AttachmentRelativePath(fileChunk.UUID) + "/" + oldFileName) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("ObsHasObject failed", err) | ctx.ServerError("ObsHasObject failed", err) | ||||
| return | return | ||||
| @@ -0,0 +1,274 @@ | |||||
| const cssnano = require('cssnano'); | |||||
| const fastGlob = require('fast-glob'); | |||||
| const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); | |||||
| const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | |||||
| const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | |||||
| const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); | |||||
| const PostCSSPresetEnv = require('postcss-preset-env'); | |||||
| const PostCSSSafeParser = require('postcss-safe-parser'); | |||||
| const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); | |||||
| const TerserPlugin = require('terser-webpack-plugin'); | |||||
| const VueLoaderPlugin = require('vue-loader/lib/plugin'); | |||||
| const {statSync} = require('fs'); | |||||
| const {resolve, parse} = require('path'); | |||||
| //const {SourceMapDevToolPlugin} = require('webpack'); | |||||
| const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | |||||
| const themes = {}; | |||||
| for (const path of glob('web_src/less/themes/*.less')) { | |||||
| themes[parse(path).name] = [path]; | |||||
| } | |||||
| const isProduction = process.env.NODE_ENV !== 'development'; | |||||
| module.exports = { | |||||
| mode: isProduction ? 'production' : 'development', | |||||
| entry: { | |||||
| index: [ | |||||
| resolve(__dirname, 'web_src/js/index.js'), | |||||
| resolve(__dirname, 'web_src/less/index.less'), | |||||
| ], | |||||
| swagger: [ | |||||
| resolve(__dirname, 'web_src/js/standalone/swagger.js'), | |||||
| ], | |||||
| jquery: [ | |||||
| resolve(__dirname, 'web_src/js/jquery.js'), | |||||
| ], | |||||
| icons: glob('node_modules/@primer/octicons/build/svg/**/*.svg'), | |||||
| ...themes, | |||||
| }, | |||||
| devtool: false, | |||||
| output: { | |||||
| path: resolve(__dirname, 'public'), | |||||
| filename: 'js/[name].js', | |||||
| chunkFilename: 'js/[name].js', | |||||
| }, | |||||
| node:{ | |||||
| fs: 'empty' | |||||
| }, | |||||
| optimization: { | |||||
| minimize: isProduction, | |||||
| minimizer: [ | |||||
| new TerserPlugin({ | |||||
| sourceMap: true, | |||||
| extractComments: false, | |||||
| terserOptions: { | |||||
| keep_fnames: /^(HTML|SVG)/, // https://github.com/fgnass/domino/issues/144 | |||||
| output: { | |||||
| comments: false, | |||||
| }, | |||||
| }, | |||||
| }), | |||||
| new OptimizeCSSAssetsPlugin({ | |||||
| cssProcessor: cssnano, | |||||
| cssProcessorOptions: { | |||||
| parser: PostCSSSafeParser, | |||||
| }, | |||||
| cssProcessorPluginOptions: { | |||||
| preset: [ | |||||
| 'default', | |||||
| { | |||||
| discardComments: { | |||||
| removeAll: true, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| }), | |||||
| ], | |||||
| splitChunks: { | |||||
| chunks: 'async', | |||||
| name: (_, chunks) => chunks.map((item) => item.name).join('-'), | |||||
| cacheGroups: { | |||||
| // this bundles all monaco's languages into one file instead of emitting 1-65.js files | |||||
| monaco: { | |||||
| test: /monaco-editor/, | |||||
| name: 'monaco', | |||||
| chunks: 'async' | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| module: { | |||||
| rules: [ | |||||
| { | |||||
| test: /\.vue$/, | |||||
| exclude: /node_modules/, | |||||
| loader: 'vue-loader', | |||||
| }, | |||||
| { | |||||
| test: require.resolve('jquery-datetimepicker'), | |||||
| use: 'imports-loader?define=>false,exports=>false', | |||||
| }, | |||||
| { | |||||
| test: /\.worker\.js$/, | |||||
| exclude: /monaco/, | |||||
| use: [ | |||||
| { | |||||
| loader: 'worker-loader', | |||||
| options: { | |||||
| name: '[name].js', | |||||
| inline: true, | |||||
| fallback: false, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| test: /\.ts$/, | |||||
| use: [ | |||||
| { | |||||
| loader: "ts-loader", | |||||
| } | |||||
| ], | |||||
| exclude: /node_modules/ | |||||
| }, | |||||
| { | |||||
| test: /\.js$/, | |||||
| exclude: /node_modules/, | |||||
| use: [ | |||||
| { | |||||
| loader: 'babel-loader', | |||||
| options: { | |||||
| cacheDirectory: true, | |||||
| cacheCompression: false, | |||||
| cacheIdentifier: [ | |||||
| resolve(__dirname, 'package.json'), | |||||
| resolve(__dirname, 'package-lock.json'), | |||||
| resolve(__dirname, 'webpack.config.js'), | |||||
| ].map((path) => statSync(path).mtime.getTime()).join(':'), | |||||
| sourceMaps: true, | |||||
| presets: [ | |||||
| [ | |||||
| '@babel/preset-env', | |||||
| { | |||||
| useBuiltIns: 'usage', | |||||
| corejs: 3, | |||||
| }, | |||||
| ], | |||||
| ], | |||||
| plugins: [ | |||||
| [ | |||||
| '@babel/plugin-transform-runtime', | |||||
| { | |||||
| regenerator: true, | |||||
| } | |||||
| ], | |||||
| '@babel/plugin-proposal-object-rest-spread', | |||||
| ], | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| test: /\.(less|css)$/i, | |||||
| use: [ | |||||
| { | |||||
| loader: MiniCssExtractPlugin.loader, | |||||
| }, | |||||
| { | |||||
| loader: 'css-loader', | |||||
| options: { | |||||
| importLoaders: 2, | |||||
| url: (_url, resourcePath) => { | |||||
| // only resolve URLs for dependencies | |||||
| return resourcePath.includes('node_modules'); | |||||
| }, | |||||
| } | |||||
| }, | |||||
| { | |||||
| loader: 'postcss-loader', | |||||
| options: { | |||||
| plugins: () => [ | |||||
| PostCSSPresetEnv(), | |||||
| ], | |||||
| }, | |||||
| }, | |||||
| { | |||||
| loader: 'less-loader', | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| test: /\.svg$/, | |||||
| use: [ | |||||
| { | |||||
| loader: 'svg-sprite-loader', | |||||
| options: { | |||||
| extract: true, | |||||
| spriteFilename: 'img/svg/icons.svg', | |||||
| symbolId: (path) => { | |||||
| const {name} = parse(path); | |||||
| if (/@primer[/\\]octicons/.test(path)) { | |||||
| return `octicon-${name}`; | |||||
| } | |||||
| return name; | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| loader: 'svgo-loader', | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| test: /\.(ttf|woff2?)$/, | |||||
| use: [ | |||||
| { | |||||
| loader: 'file-loader', | |||||
| options: { | |||||
| name: '[name].[ext]', | |||||
| outputPath: 'fonts/', | |||||
| publicPath: (url) => `../fonts/${url}`, // seems required for monaco's font | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| plugins: [ | |||||
| new VueLoaderPlugin(), | |||||
| // avoid generating useless js output files for css- and svg-only chunks | |||||
| new FixStyleOnlyEntriesPlugin({ | |||||
| extensions: ['less', 'scss', 'css', 'svg'], | |||||
| silent: true, | |||||
| }), | |||||
| new MiniCssExtractPlugin({ | |||||
| filename: 'css/[name].css', | |||||
| chunkFilename: 'css/[name].css', | |||||
| }), | |||||
| //new SourceMapDevToolPlugin({ | |||||
| //filename: 'js/[name].js.map', | |||||
| //include: [ | |||||
| //'js/index.js', | |||||
| //], | |||||
| //}), | |||||
| new SpriteLoaderPlugin({ | |||||
| plainSprite: true, | |||||
| }), | |||||
| new MonacoWebpackPlugin({ | |||||
| filename: 'js/monaco-[name].worker.js', | |||||
| }) | |||||
| ], | |||||
| performance: { | |||||
| hints: false, | |||||
| maxEntrypointSize: Infinity, | |||||
| maxAssetSize: Infinity, | |||||
| }, | |||||
| resolve: { | |||||
| symlinks: false, | |||||
| alias: { | |||||
| vue$: 'vue/dist/vue.esm.js', // needed because vue's default export is the runtime only | |||||
| }, | |||||
| extensions: ['.tsx', '.ts', '.js'] | |||||
| }, | |||||
| watchOptions: { | |||||
| ignored: [ | |||||
| 'node_modules/**', | |||||
| ], | |||||
| }, | |||||
| stats: { | |||||
| children: false, | |||||
| }, | |||||
| }; | |||||