| @@ -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_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_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 | |||
| lint-frontend: node_modules | |||
| npx eslint web_src/js webpack.config.js | |||
| npx eslint web_src/js $(WEBPACK_CONFIGS) | |||
| npx stylelint web_src/less | |||
| .PHONY: watch-frontend | |||
| @@ -504,7 +506,7 @@ install: $(wildcard *.go) | |||
| build: frontend backend | |||
| .PHONY: frontend | |||
| frontend: node-check $(FOMANTIC_DEST) $(WEBPACK_DEST) | |||
| frontend: node-check webpack_prepare $(FOMANTIC_DEST) $(WEBPACK_DEST) webpack_end | |||
| .PHONY: backend | |||
| backend: go-check generate $(EXECUTABLE) | |||
| @@ -596,6 +598,19 @@ $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules | |||
| .PHONY: webpack | |||
| 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 | |||
| rm -rf $(WEBPACK_DEST_DIRS) | |||
| @@ -114,7 +114,7 @@ socket.onmessage = function (e) { | |||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>" | |||
| } | |||
| 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); | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
| @@ -156,20 +156,21 @@ socket.onmessage = function (e) { | |||
| function getTaskLink(record){ | |||
| var re = getRepoLink(record); | |||
| if(record.OpType == 24){ | |||
| return re + "/datasets?type=" + record.Content; | |||
| re = re + "/datasets?type=" + record.Content; | |||
| }else if(record.OpType == 25){ | |||
| return re + "/cloudbrain/" + record.Content; | |||
| re = re + "/cloudbrain/" + record.RefName; | |||
| }else if(record.OpType == 26){ | |||
| return re + "/modelarts/notebook/" + record.Content; | |||
| re = re + "/modelarts/notebook/" + record.Content; | |||
| }else if(record.OpType == 27){ | |||
| return re + "/modelarts/train-job/" + record.Content; | |||
| re = re + "/modelarts/train-job/" + record.Content; | |||
| }else if(record.OpType == 28){ | |||
| return re + "/modelarts/inference-job/" + record.Content; | |||
| re = re + "/modelarts/inference-job/" + record.Content; | |||
| }else if(record.OpType == 29){ | |||
| return re + "/cloudbrain/benchmark/" + record.Content; | |||
| re = re + "/cloudbrain/benchmark/" + record.RefName; | |||
| }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; | |||
| } | |||
| @@ -184,7 +185,7 @@ function getMsg(record){ | |||
| } | |||
| html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">" | |||
| html += " <div class=\"middle aligned content nowrap\">" | |||
| html += " <a href=\"/" + name + "\" title=\"\">" + name + "</a>" | |||
| html += " <a href=\"/" + encodeURI(name) + "\" title=\"\">" + name + "</a>" | |||
| return html; | |||
| } | |||
| @@ -196,7 +197,7 @@ function getRepotext(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){ | |||
| return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record); | |||
| return encodeURI("/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record)); | |||
| } | |||
| function getPRText(record){ | |||
| if(record.Repo.Alias){ | |||
| @@ -241,7 +242,7 @@ function getPRText(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){ | |||
| @@ -512,7 +512,12 @@ func GetSuccessChunks(ctx *context.Context) { | |||
| return | |||
| } | |||
| } 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 { | |||
| ctx.ServerError("ObsHasObject failed", err) | |||
| 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, | |||
| }, | |||
| }; | |||